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];
}