using System.Buffers.Binary; using System.Net; using Common; using Microsoft.AspNetCore.Cors; 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 { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 页面 /// [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.WriteFIFO(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) { logger.Info($"Get device {address} ID code: 0x{ret.Value:X4}"); return TypedResults.Ok(ret.Value); } else { logger.Error(ret.Error); return TypedResults.InternalServerError(ret.Error); } } /// /// 获取状态寄存器 /// /// 设备地址 /// 设备端口 [HttpGet("ReadStatusReg")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async ValueTask ReadStatusReg(string address, int port) { var jtagCtrl = new JtagClient.Jtag(address, port); var ret = await jtagCtrl.ReadStatusReg(); if (ret.IsSuccessful) { var binaryValue = Common.String.Reverse(Convert.ToString(ret.Value, 2).PadLeft(32, '0')); var decodeValue = new JtagClient.JtagStatusReg(ret.Value); logger.Info($"Read device {address} Status Register: \n\t 0b{binaryValue} \n\t {decodeValue}"); return TypedResults.Ok(new { original = ret.Value, binaryValue, decodeValue, }); } else { logger.Error(ret.Error); return TypedResults.InternalServerError(ret.Error); } } /// /// 上传比特流文件 /// /// 设备地址 /// 比特流文件 [HttpPost("UploadBitstream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async ValueTask UploadBitstream(string address, IFormFile file) { if (file == null || file.Length == 0) return TypedResults.BadRequest("未选择文件"); // 生成安全的文件名(避免路径遍历攻击) var fileName = Path.GetRandomFileName(); var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"bitstream/{address}"); // 如果存在文件,则删除原文件再上传 if (Directory.Exists(uploadsFolder)) { Directory.Delete(uploadsFolder, true); } Directory.CreateDirectory(uploadsFolder); var filePath = Path.Combine(uploadsFolder, fileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } logger.Info($"Device {address} Upload Bitstream Successfully"); return TypedResults.Ok("Bitstream Upload Successfully"); } /// /// 通过Jtag下载比特流文件 /// /// 设备地址 /// 设备端口 [HttpPost("DownloadBitstream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async ValueTask DownloadBitstream(string address, int port) { // 检查文件 var fileDir = Path.Combine(Environment.CurrentDirectory, $"bitstream/{address}"); if (!Directory.Exists(fileDir)) return TypedResults.BadRequest("Empty bitstream, Please upload it first"); try { // 读取文件 var filePath = Directory.GetFiles(fileDir)[0]; using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open)) { if (fileStream is null || fileStream.Length <= 0) return TypedResults.BadRequest("Wrong bitstream, Please upload it again"); // 定义缓冲区大小: 32KB byte[] buffer = new byte[32 * 1024]; byte[] revBuffer = new byte[32 * 1024]; long totalBytesRead = 0; // 使用异步流读取文件 using (var memoryStream = new MemoryStream()) { int bytesRead; while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { // 反转 32bits var retBuffer = Common.Number.ReverseBytes(buffer, 4); if (!retBuffer.IsSuccessful) return TypedResults.InternalServerError(retBuffer.Error); revBuffer = retBuffer.Value; for (int i = 0; i < buffer.Length; i++) { revBuffer[i] = BinaryPrimitives.ReverseEndianness(revBuffer[i]); } await memoryStream.WriteAsync(revBuffer, 0, bytesRead); totalBytesRead += bytesRead; } // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存) var fileBytes = memoryStream.ToArray(); // 下载比特流 var jtagCtrl = new JtagClient.Jtag(address, port); var ret = await jtagCtrl.DownloadBitstream(fileBytes); if (ret.IsSuccessful) { logger.Info($"Device {address} dowload bitstream successfully"); return TypedResults.Ok(ret.Value); } else { logger.Error(ret.Error); return TypedResults.InternalServerError(ret.Error); } } } } catch (Exception error) { return TypedResults.InternalServerError(error); } finally { } } } /// /// 远程更新 /// [ApiController] [Route("api/[controller]")] public class RemoteUpdater : ControllerBase { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 上传远程更新比特流文件 /// /// 设备地址 /// 比特流文件 [HttpPost("UploadBitstream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] public async ValueTask UploadBitstream(string address, IFormFile file) { if (file == null || file.Length == 0) return TypedResults.BadRequest("未选择文件"); // 生成安全的文件名(避免路径遍历攻击) var fileName = Path.GetRandomFileName(); var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"bitstream/RemoteUpdate/{address}"); // 如果存在文件,则删除原文件再上传 if (Directory.Exists(uploadsFolder)) { Directory.Delete(uploadsFolder, true); } Directory.CreateDirectory(uploadsFolder); var filePath = Path.Combine(uploadsFolder, fileName); using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } logger.Info($"Device {address} Upload Bitstream Successfully"); return TypedResults.Ok("Bitstream Upload Successfully"); } /// /// 远程更新比特流文件 /// /// 设备地址 /// 设备端口 /// 比特流位号 [HttpPost("DownloadBitstream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status500InternalServerError)] public async ValueTask UpdateBitstream(string address, int port, int bitstreamNum) { // 检查文件 var fileDir = Path.Combine(Environment.CurrentDirectory, $"bitstream/RemoteUpdate/{address}"); if (!Directory.Exists(fileDir)) return TypedResults.BadRequest("Empty bitstream, Please upload it first"); try { // 读取文件 var filePath = Directory.GetFiles(fileDir)[0]; using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open)) { if (fileStream is null || fileStream.Length <= 0) return TypedResults.BadRequest("Wrong bitstream, Please upload it again"); // 定义缓冲区大小: 32KB byte[] buffer = new byte[32 * 1024]; byte[] revBuffer = new byte[32 * 1024]; long totalBytesRead = 0; // 使用异步流读取文件 using (var memoryStream = new MemoryStream()) { int bytesRead; while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { // 反转 32bits var retBuffer = Common.Number.ReverseBytes(buffer, 4); if (!retBuffer.IsSuccessful) return TypedResults.InternalServerError(retBuffer.Error); revBuffer = retBuffer.Value; for (int i = 0; i < buffer.Length; i++) { revBuffer[i] = BinaryPrimitives.ReverseEndianness(revBuffer[i]); } await memoryStream.WriteAsync(revBuffer, 0, bytesRead); totalBytesRead += bytesRead; } // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存) var restStreamLen = memoryStream.Length % (4 * 1024); if (restStreamLen != 0) { var appendLen = ((int)(4 * 1024 - restStreamLen)); var bytesAppend = new byte[appendLen]; Array.Fill(bytesAppend, 0xFF); await memoryStream.WriteAsync(bytesAppend, 0, appendLen); } var fileBytes = memoryStream.ToArray(); // 下载比特流 var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port); var ret = await remoteUpdater.UpdateBitstream(bitstreamNum, fileBytes); if (ret.IsSuccessful) { logger.Info($"Device {address} Update bitstream successfully"); return TypedResults.Ok(ret.Value); } else { logger.Error(ret.Error); return TypedResults.InternalServerError(ret.Error); } } } } catch (Exception error) { return TypedResults.InternalServerError(error); } } } /// /// 数据控制器 /// [ApiController] [Route("api/[controller]")] public class Data : ControllerBase { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 创建数据库表 /// /// 插入的记录数 [EnableCors("Development")] [HttpPost("CreateTable")] public IResult CreateTables() { using var db = new Database.AppDataConnection(); db.CreateAllTables(); return TypedResults.Ok(); } /// /// 删除数据库表 /// /// 插入的记录数 [EnableCors("Development")] [HttpDelete("DropTables")] public IResult DropTables() { using var db = new Database.AppDataConnection(); db.DropAllTables(); return TypedResults.Ok(); } /// /// 获取所有用户 /// /// 用户列表 [HttpGet("AllUsers")] public IResult AllUsers() { using var db = new Database.AppDataConnection(); var ret = db.User.ToList(); return TypedResults.Ok(ret); } /// /// 注册新用户 /// /// 用户名 /// 操作结果 [HttpPost("SignUpUser")] public IResult SignUpUser(string name) { if (name.Length > 255) return TypedResults.BadRequest("Name Couln't over 255 characters"); using var db = new Database.AppDataConnection(); var ret = db.AddUser(name); return TypedResults.Ok(ret); } } /// /// 日志控制器 /// [ApiController] [Route("api/[controller]")] public class Log : ControllerBase { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 日志文件路径 /// private readonly string _logFilePath = Directory.GetFiles(Directory.GetCurrentDirectory())[0]; }