750 lines
26 KiB
C#
750 lines
26 KiB
C#
using System.Net;
|
|
using Common;
|
|
using DotNext;
|
|
using Microsoft.AspNetCore.Cors;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Newtonsoft.Json;
|
|
using WebProtocol;
|
|
|
|
namespace server.Controllers;
|
|
|
|
// /// <summary>
|
|
// /// [TODO:description]
|
|
// /// </summary>
|
|
// public class HomeController : ControllerBase
|
|
// {
|
|
// private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
//
|
|
// string INDEX_HTML_PATH = Path.Combine(Environment.CurrentDirectory, "index.html");
|
|
//
|
|
// /// <summary>
|
|
// /// [TODO:description]
|
|
// /// </summary>
|
|
// /// <returns>[TODO:return]</returns>
|
|
// [HttpGet("/")]
|
|
// public IResult Index()
|
|
// {
|
|
// return TypedResults.Content("Hello", "text/html");
|
|
// }
|
|
//
|
|
// // [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
// // public IResult Error()
|
|
// // {
|
|
// // return TypedResults.Ok();
|
|
// // }
|
|
//
|
|
// /// <summary>
|
|
// /// [TODO:description]
|
|
// /// </summary>
|
|
// /// <returns>[TODO:return]</returns>
|
|
// [HttpGet("/hello")]
|
|
// [HttpPost("/hello")]
|
|
// public IActionResult Hello()
|
|
// {
|
|
// string randomString = Guid.NewGuid().ToString();
|
|
// return this.Ok($"Hello World! GUID: {randomString}");
|
|
// }
|
|
// }
|
|
|
|
/// <summary>
|
|
/// UDP API
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class UDPController : ControllerBase
|
|
{
|
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
private const string LOCALHOST = "127.0.0.1";
|
|
|
|
/// <summary>
|
|
/// 页面
|
|
/// </summary>
|
|
[HttpGet]
|
|
public string Index()
|
|
{
|
|
return "This is UDP Controller";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 发送字符串
|
|
/// </summary>
|
|
/// <param name="address">IPV4 或者 IPV6 地址</param>
|
|
/// <param name="port">设备端口号</param>
|
|
/// <param name="text">发送的文本</param>
|
|
/// <response code="200">发送成功</response>
|
|
/// <response code="500">发送失败</response>
|
|
[HttpPost("SendString")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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(); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 发送二进制数据
|
|
/// </summary>
|
|
/// <param name="address" example="127.0.0.1">IPV4 或者 IPV6 地址</param>
|
|
/// <param name="port" example="1234">设备端口号</param>
|
|
/// <param name="bytes" example="FFFFAAAA">16进制文本</param>
|
|
[HttpPost("SendBytes")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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(); }
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 发送地址包
|
|
/// </summary>
|
|
/// <param name="address">IP地址</param>
|
|
/// <param name="port">UDP 端口号</param>
|
|
/// <param name="opts">地址包选项</param>
|
|
[HttpPost("SendAddrPackage")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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(); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 发送数据包
|
|
/// </summary>
|
|
/// <param name="address">IP地址</param>
|
|
/// <param name="port">UDP 端口号</param>
|
|
/// <param name="data">16进制数据</param>
|
|
[HttpPost("SendDataPackage")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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(); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取指定IP地址接受的数据列表
|
|
/// </summary>
|
|
/// <param name="address">IP地址</param>
|
|
[HttpGet("GetRecvDataArray")]
|
|
[ProducesResponseType(typeof(List<UDPData>), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Jtag API
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class JtagController : ControllerBase
|
|
{
|
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
private const string BITSTREAM_PATH = "bitstream/Jtag";
|
|
|
|
/// <summary>
|
|
/// 页面
|
|
/// </summary>
|
|
[HttpGet]
|
|
public string Index()
|
|
{
|
|
return "This is Jtag Controller";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 执行一个Jtag命令
|
|
/// </summary>
|
|
/// <param name="address"> 设备地址 </param>
|
|
/// <param name="port"> 设备端口 </param>
|
|
/// <param name="hexDevAddr"> 16进制设备目的地址(Jtag) </param>
|
|
/// <param name="hexCmd"> 16进制命令 </param>
|
|
[HttpPost("RunCommand")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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); }
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 获取Jtag ID Code
|
|
/// </summary>
|
|
/// <param name="address"> 设备地址 </param>
|
|
/// <param name="port"> 设备端口 </param>
|
|
[HttpGet("GetDeviceIDCode")]
|
|
[ProducesResponseType(typeof(uint), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取状态寄存器
|
|
/// </summary>
|
|
/// <param name="address"> 设备地址 </param>
|
|
/// <param name="port"> 设备端口 </param>
|
|
[HttpGet("ReadStatusReg")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> 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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 上传比特流文件
|
|
/// </summary>
|
|
/// <param name="address"> 设备地址 </param>
|
|
/// <param name="file">比特流文件</param>
|
|
[HttpPost("UploadBitstream")]
|
|
[EnableCors("Users")]
|
|
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
|
|
public async ValueTask<IResult> 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_PATH}/{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(true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 通过Jtag下载比特流文件
|
|
/// </summary>
|
|
/// <param name="address"> 设备地址 </param>
|
|
/// <param name="port"> 设备端口 </param>
|
|
[HttpPost("DownloadBitstream")]
|
|
[EnableCors("Users")]
|
|
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> DownloadBitstream(string address, int port)
|
|
{
|
|
// 检查文件
|
|
var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{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;
|
|
|
|
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
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// [TODO:description]
|
|
/// </summary>
|
|
/// <param name="address">[TODO:parameter]</param>
|
|
/// <param name="port">[TODO:parameter]</param>
|
|
/// <param name="portNum">[TODO:parameter]</param>
|
|
/// <returns>[TODO:return]</returns>
|
|
[HttpPost("BoundaryScan")]
|
|
[EnableCors("Users")]
|
|
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> BoundaryScan(string address, int port, int portNum)
|
|
{
|
|
var jtagCtrl = new JtagClient.Jtag(address, port);
|
|
var ret = await jtagCtrl.BoundaryScan(portNum);
|
|
if (!ret.IsSuccessful)
|
|
{
|
|
if (ret.Error is ArgumentException)
|
|
return TypedResults.BadRequest(ret.Error);
|
|
else return TypedResults.InternalServerError(ret.Error);
|
|
}
|
|
|
|
return TypedResults.Ok(ret.Value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 远程更新
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class RemoteUpdater : ControllerBase
|
|
{
|
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
private const string BITSTREAM_PATH = "bitstream/RemoteUpdate";
|
|
|
|
/// <summary>
|
|
/// 上传远程更新比特流文件
|
|
/// </summary>
|
|
/// <param name="address"> 设备地址 </param>
|
|
/// <param name="goldenBitream">黄金比特流文件</param>
|
|
/// <param name="bitstream1">比特流文件1</param>
|
|
/// <param name="bitstream2">比特流文件2</param>
|
|
/// <param name="bitstream3">比特流文件3</param>
|
|
/// <returns>上传结果</returns>
|
|
[HttpPost("UploadBitstream")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
public async ValueTask<IResult> UploadBitstreams(
|
|
string address,
|
|
IFormFile? goldenBitream,
|
|
IFormFile? bitstream1,
|
|
IFormFile? bitstream2,
|
|
IFormFile? bitstream3)
|
|
{
|
|
if ((goldenBitream is null || goldenBitream.Length == 0) &&
|
|
(bitstream1 is null || bitstream1.Length == 0) &&
|
|
(bitstream2 is null || bitstream2.Length == 0) &&
|
|
(bitstream3 is null || bitstream3.Length == 0))
|
|
return TypedResults.BadRequest("未选择文件");
|
|
|
|
// 生成安全的文件名(避免路径遍历攻击)
|
|
var fileName = Path.GetRandomFileName();
|
|
var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
|
|
|
|
// 如果存在文件,则删除原文件再上传
|
|
if (Directory.Exists(uploadsFolder))
|
|
{
|
|
Directory.Delete(uploadsFolder, true);
|
|
}
|
|
Directory.CreateDirectory(uploadsFolder);
|
|
|
|
for (int bitstreamNum = 0; bitstreamNum < 4; bitstreamNum++)
|
|
{
|
|
IFormFile file;
|
|
if (bitstreamNum == 0 && goldenBitream is not null)
|
|
file = goldenBitream;
|
|
else if (bitstreamNum == 1 && bitstream1 is not null)
|
|
file = bitstream1;
|
|
else if (bitstreamNum == 2 && bitstream2 is not null)
|
|
file = bitstream2;
|
|
else if (bitstreamNum == 3 && bitstream3 is not null)
|
|
file = bitstream3;
|
|
else continue;
|
|
|
|
var fileFolder = Path.Combine(uploadsFolder, bitstreamNum.ToString());
|
|
Directory.CreateDirectory(fileFolder);
|
|
|
|
var filePath = Path.Combine(fileFolder, 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");
|
|
}
|
|
|
|
private async ValueTask<Result<byte[]>> ProcessBitstream(string filePath)
|
|
{
|
|
using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open))
|
|
{
|
|
if (fileStream is null || fileStream.Length <= 0)
|
|
return new(new ArgumentException("Wrong bitstream path"));
|
|
|
|
// 定义缓冲区大小: 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 new(retBuffer.Error);
|
|
revBuffer = retBuffer.Value;
|
|
|
|
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<byte>(bytesAppend, 0xFF);
|
|
await memoryStream.WriteAsync(bytesAppend, 0, appendLen);
|
|
}
|
|
|
|
return new(memoryStream.ToArray());
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 远程更新单个比特流文件
|
|
/// </summary>
|
|
/// <param name="address"> 设备地址 </param>
|
|
/// <param name="port"> 设备端口 </param>
|
|
/// <param name="bitstreamNum"> 比特流位号 </param>
|
|
[HttpPost("DownloadBitstream")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> UpdateBitstream(string address, int port, int bitstreamNum)
|
|
{
|
|
// 检查文件
|
|
var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}/{bitstreamNum}");
|
|
if (!Directory.Exists(fileDir))
|
|
return TypedResults.BadRequest("Empty bitstream, Please upload it first");
|
|
|
|
try
|
|
{
|
|
// 读取文件
|
|
var filePath = Directory.GetFiles(fileDir)[0];
|
|
|
|
var fileBytes = await ProcessBitstream(filePath);
|
|
if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error);
|
|
|
|
// 下载比特流
|
|
var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port);
|
|
var ret = await remoteUpdater.UpdateBitstream(bitstreamNum, fileBytes.Value);
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 下载多个比特流文件
|
|
/// </summary>
|
|
/// <param name="address">设备地址</param>
|
|
/// <param name="port">设备端口</param>
|
|
/// <param name="bitstreamNum">比特流编号</param>
|
|
/// <returns>总共上传比特流的数量</returns>
|
|
[HttpPost("DownloadMultiBitstreams")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> DownloadMultiBitstreams(string address, int port, int? bitstreamNum)
|
|
{
|
|
// 检查文件
|
|
var bitstreamsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}");
|
|
if (!Directory.Exists(bitstreamsFolder))
|
|
return TypedResults.BadRequest("Empty bitstream, Please upload it first");
|
|
|
|
try
|
|
{
|
|
var bitstreams = new List<byte[]?>() { null, null, null, null };
|
|
int cnt = 0; // 上传比特流数量
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
var bitstreamDir = Path.Combine(bitstreamsFolder, i.ToString());
|
|
if (!Directory.Exists(bitstreamDir))
|
|
continue;
|
|
cnt++;
|
|
|
|
// 读取文件
|
|
var filePath = Directory.GetFiles(bitstreamDir)[0];
|
|
var fileBytes = await ProcessBitstream(filePath);
|
|
if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error);
|
|
bitstreams[i] = fileBytes.Value;
|
|
}
|
|
|
|
// 下载比特流
|
|
var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port);
|
|
{
|
|
var ret = await remoteUpdater.UploadBitstreams(bitstreams[0], bitstreams[1], bitstreams[2], bitstreams[3]);
|
|
if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error);
|
|
if (!ret.Value) return TypedResults.InternalServerError("Upload MultiBitstreams failed");
|
|
}
|
|
|
|
if (bitstreamNum is not null)
|
|
{
|
|
var ret = await remoteUpdater.HotResetBitstream(bitstreamNum ?? 0);
|
|
if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error);
|
|
if (!ret.Value) return TypedResults.InternalServerError("Hot reset failed");
|
|
}
|
|
return TypedResults.Ok(cnt);
|
|
}
|
|
catch (Exception error)
|
|
{
|
|
return TypedResults.InternalServerError(error);
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 热复位比特流文件
|
|
/// </summary>
|
|
/// <param name="address">设备地址</param>
|
|
/// <param name="port">设备端口</param>
|
|
/// <param name="bitstreamNum">比特流编号</param>
|
|
/// <returns>操作结果</returns>
|
|
[HttpPost("HotResetBitstream")]
|
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
|
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
|
public async ValueTask<IResult> HotResetBitstream(string address, int port, int bitstreamNum)
|
|
{
|
|
var remoteUpdater = new RemoteUpdate.RemoteUpdateClient(address, port);
|
|
var ret = await remoteUpdater.HotResetBitstream(bitstreamNum);
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 数据控制器
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class Data : ControllerBase
|
|
{
|
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
/// <summary>
|
|
/// 创建数据库表
|
|
/// </summary>
|
|
/// <returns>插入的记录数</returns>
|
|
[EnableCors("Development")]
|
|
[HttpPost("CreateTable")]
|
|
public IResult CreateTables()
|
|
{
|
|
using var db = new Database.AppDataConnection();
|
|
db.CreateAllTables();
|
|
return TypedResults.Ok();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 删除数据库表
|
|
/// </summary>
|
|
/// <returns>插入的记录数</returns>
|
|
[EnableCors("Development")]
|
|
[HttpDelete("DropTables")]
|
|
public IResult DropTables()
|
|
{
|
|
using var db = new Database.AppDataConnection();
|
|
db.DropAllTables();
|
|
return TypedResults.Ok();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取所有用户
|
|
/// </summary>
|
|
/// <returns>用户列表</returns>
|
|
[HttpGet("AllUsers")]
|
|
public IResult AllUsers()
|
|
{
|
|
using var db = new Database.AppDataConnection();
|
|
var ret = db.User.ToList();
|
|
return TypedResults.Ok(ret);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 注册新用户
|
|
/// </summary>
|
|
/// <param name="name">用户名</param>
|
|
/// <returns>操作结果</returns>
|
|
[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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 日志控制器
|
|
/// </summary>
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class Log : ControllerBase
|
|
{
|
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
/// <summary>
|
|
/// 日志文件路径
|
|
/// </summary>
|
|
private readonly string _logFilePath = Directory.GetFiles(Directory.GetCurrentDirectory())[0];
|
|
|
|
}
|
|
|