try to fix bug, and add schema to swagger

This commit is contained in:
SikongJueluo 2025-04-13 21:22:55 +08:00
parent c9660633f0
commit 5fa4860bfb
No known key found for this signature in database
5 changed files with 239 additions and 144 deletions

View File

@ -40,16 +40,17 @@ try
Description = "Use FPGA in the cloud",
Version = "v1"
});
// Generate Doc and Exam
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);
// 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);
});
var app = builder.Build();
@ -83,13 +84,13 @@ try
// API Get
app.MapGet("/", () => Results.Redirect("/swagger"));
app.MapGet("/api/GetRecvDataArray", Router.API.GetRecvDataArray);
app.MapPut("/api/SendString", Router.API.SendString);
app.MapPost("/api/SendString", Router.API.SendString);
// API Put
app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage);
app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage);
// API Jtag Put
app.MapPut("/api/jtag/RunCommand", Router.API.Jtag.RunCommand);
app.MapPut("/api/jtag/GetIDCode", Router.API.Jtag.GetDeviceIDCode);
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.Run("http://localhost:5000");
}

View File

@ -235,13 +235,13 @@ class Jtag
var ret = false;
var opts = new SendAddrPackOptions();
opts.burstType = BurstType.FixedBurst;
opts.burstLength = 0;
opts.commandID = 0;
opts.address = devAddr;
opts.BurstType = BurstType.FixedBurst;
opts.BurstLength = 0;
opts.CommandID = 0;
opts.Address = devAddr;
// Read Jtag State Register
opts.isWrite = false;
opts.IsWrite = false;
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send Address Package Failed!");
@ -249,26 +249,19 @@ class Jtag
if (!MsgBus.IsRunning)
throw new Exception("Message Bus not Working!");
var data = await MsgBus.UDPServer.FindDataAsync(address);
if (!data.HasValue)
throw new Exception("Get None after Time out!");
var retPack = await MsgBus.UDPServer.WaitForDataAsync(address, port);
if (!retPack.IsSuccessful || !retPack.Value.IsSuccessful)
throw new Exception("Send address package failed");
var recvData = data.Value;
if (recvData.Address != address || recvData.Port != port)
throw new Exception("Receive Data From Wrong Board!");
var retPackOpts = retPack.Value.Options;
if (retPackOpts.Data is null)
throw new Exception($"Data is Null, package: {retPackOpts.ToString()}");
var retPack = RecvDataPackage.FromBytes(recvData.Data);
if (!retPack.IsSuccessful)
throw new Exception("Not RecvDataPackage!", retPack.Error);
if (retPack.Value.Options.data is null)
throw new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}");
var retPackLen = retPack.Value.Options.data.Length;
var retPackLen = retPackOpts.Data.Length;
if (retPackLen != 4)
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
return (uint)(NumberProcessor.BytesToNumber(retPack.Value.Options.data));
return (uint)(NumberProcessor.BytesToNumber(retPackOpts.Data));
}
public async ValueTask<Result<RecvDataPackage>> RunCommand(uint devAddr, uint command)
@ -276,59 +269,60 @@ class Jtag
var ret = false;
var opts = new SendAddrPackOptions();
opts.burstType = BurstType.FixedBurst;
opts.burstLength = 0;
opts.commandID = 0;
opts.address = devAddr;
opts.BurstType = BurstType.FixedBurst;
opts.BurstLength = 0;
opts.CommandID = 0;
opts.Address = devAddr;
// Write Jtag State Register
opts.isWrite = true;
opts.IsWrite = true;
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send 1st Address Package Failed!");
if (!ret) throw new Exception("Send 1st address package failed!");
// Check Msg Bus
if (!MsgBus.IsRunning)
throw new Exception("Message bus not working!");
// Wait for Write Ack
{
var udpResp = await MsgBus.UDPServer.WaitForAckAsync(address, port);
if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful)
throw new Exception("Send address package failed");
}
// Send Data Package
ret = await UDPClientPool.SendDataPackAsync(ep,
new SendDataPackage(NumberProcessor.NumberToBytes(command, 4).Value));
if (!ret) throw new Exception("Send Data Package Failed!");
if (!ret) throw new Exception("Send data package failed!");
// Read Jtag State Register
opts.isWrite = false;
opts.address = JtagAddr.STATE;
opts.IsWrite = false;
opts.Address = JtagAddr.STATE;
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send 2rd Address Package Failed!");
// Wait for Read Data
{
var udpResp = await MsgBus.UDPServer.WaitForDataAsync(address, port);
if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful)
throw new Exception("Send address package failed");
// Wait for Ack
if (!MsgBus.IsRunning)
throw new Exception("Message Bus not Working!");
var data = await MsgBus.UDPServer.FindDataAsync(address);
if (!data.HasValue)
throw new Exception("Get None after Time out!");
var recvData = data.Value;
if (recvData.Address != address || recvData.Port != port)
throw new Exception("Receive Data From Wrong Board!");
var retPack = RecvDataPackage.FromBytes(recvData.Data);
if (!retPack.IsSuccessful)
throw new Exception("Not RecvDataPackage!", retPack.Error);
return retPack;
return udpResp.Value;
}
}
public async ValueTask<Result<bool>> RunCommand(uint devAddr, uint command, uint result, uint resultMask = 0xFF_FF_FF_FF)
public async ValueTask<Result<bool>> RunCommand
(uint devAddr, uint command, uint result, uint resultMask = 0xFF_FF_FF_FF)
{
var ret = false;
var retPack = await RunCommand(devAddr, command);
if (retPack.Value.Options.data is null)
if (retPack.Value.Options.Data is null)
throw new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}");
var retPackLen = retPack.Value.Options.data.Length;
var retPackLen = retPack.Value.Options.Data.Length;
if (retPackLen != 4)
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
if (NumberProcessor.BitsCheck(
NumberProcessor.BytesToNumber(retPack.Value.Options.data).Value, result, resultMask))
NumberProcessor.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask))
ret = true;
return ret;

View File

@ -2,6 +2,7 @@ using System.Net;
using Common;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using WebProtocol;
namespace Router
{
@ -54,28 +55,24 @@ namespace Router
}
[HttpPost]
/// <summary>
/// 发送地址包
/// </summary>
/// <param name="address" example="127.0.0.1">IP地址</param>
/// <param name="port" example="1234">UDP 端口号</param>
/// <param name="opts">地址包选项</param>
[HttpPost("{address}/{port}")]
[ProducesResponseType(200)]
[ProducesResponseType(500)]
public static async ValueTask<IResult> SendAddrPackage(
string address,
int port,
// WebProtocol.BurstType burstType,
// byte commandID,
// bool isWrite,
// byte burstLength,
// UInt32 devAddress)
WebProtocol.SendAddrPackOptions opts)
[FromBody] SendAddrPackOptions opts)
{
// WebProtocol.SendAddrPackOptions opts;
// opts.burstType = burstType;
// opts.commandID = commandID;
// opts.isWrite = isWrite;
// opts.burstLength = burstLength;
// opts.address = devAddress;
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts));
if (ret) { return Results.Json(new Response() { IsSuccess = true }); }
else { return Results.Json(new Response() { IsSuccess = false }); }
if (ret) { return TypedResults.Ok(); }
else { return TypedResults.InternalServerError(); }
}
public static async ValueTask<IResult> SendDataPackage(string address, int port, string data)
@ -87,7 +84,7 @@ namespace Router
else { return Results.Json(new Response() { IsSuccess = false }); }
}
[HttpGet()]
[HttpGet("{address}")]
public static async ValueTask<IResult> GetRecvDataArray(string address)
{
var ret = await MsgBus.UDPServer.GetDataArrayAsync(address);

View File

@ -11,19 +11,23 @@ public class UDPData
/// <summary>
/// 接受到的时间
/// </summary>
public DateTime DateTime { get; set; }
public required DateTime DateTime { get; set; }
/// <summary>
/// 发送来源的IP地址
/// </summary>
public string Address { get; set; }
public required string Address { get; set; }
/// <summary>
/// 发送来源的端口号
/// </summary>
public int Port { get; set; }
public required int Port { get; set; }
/// <summary>
/// 接受到的数据
/// </summary>
public byte[] Data { get; set; }
public required byte[] Data { get; set; }
/// <summary>
/// 是否被读取过
/// </summary>
public required bool HasRead { get; set; }
/// <summary>
/// 将UDP Data 转化为Json 格式字符串
@ -94,6 +98,8 @@ public class UDPServer
{
data = udpData[ipAddr][0];
udpData[ipAddr].RemoveAt(0);
logger.Debug($"Find UDP Data: {data.ToString()}");
break;
}
}
@ -103,6 +109,7 @@ public class UDPServer
if (data == null)
{
logger.Trace("Get nothing even after time out");
return Optional.None<UDPData>();
}
else
@ -137,6 +144,8 @@ public class UDPServer
{
data = udpData[ipAddr][0];
udpData[ipAddr].RemoveAt(0);
logger.Debug($"Find UDP Data: {data.ToString()}");
break;
}
}
@ -146,6 +155,7 @@ public class UDPServer
if (data == null)
{
logger.Trace("Get nothing even after time out");
return Optional.None<UDPData>();
}
else
@ -154,6 +164,12 @@ public class UDPServer
}
}
/// <summary>
/// 获取还未被读取的数据列表
/// </summary>
/// <param name="ipAddr">IP地址</param>
/// <param name="timeout">超时时间</param>
/// <returns>数据列表</returns>
public async ValueTask<Optional<List<UDPData>>> GetDataArrayAsync(string ipAddr, int timeout = 1000)
{
List<UDPData>? data = null;
@ -186,6 +202,56 @@ public class UDPServer
}
}
/// <summary>
/// 异步等待读响应或写响应
/// </summary>
/// <param name="address">IP地址</param>
/// <param name="port">UDP 端口</param>
/// <param name="timeout">超时时间范围</param>
/// <returns>接收响应包</returns>
public async ValueTask<Result<WebProtocol.RecvRespPackage>> WaitForAckAsync
(string address, int port, int timeout = 1000)
{
var data = await FindDataAsync(address, timeout);
if (!data.HasValue)
throw new Exception("Get None even after time out!");
var recvData = data.Value;
if (recvData.Address != address || recvData.Port != port)
throw new Exception("Receive Data From Wrong Board!");
var retPack = WebProtocol.RecvRespPackage.FromBytes(recvData.Data);
if (!retPack.IsSuccessful)
throw new Exception("Not RecvDataPackage!", retPack.Error);
return retPack.Value;
}
/// <summary>
/// 异步等待数据
/// </summary>
/// <param name="address">IP地址</param>
/// <param name="port">UDP 端口</param>
/// <param name="timeout">超时时间范围</param>
/// <returns>接收数据包</returns>
public async ValueTask<Result<WebProtocol.RecvDataPackage>> WaitForDataAsync
(string address, int port, int timeout = 1000)
{
var data = await FindDataAsync(address, timeout);
if (!data.HasValue)
throw new Exception("Get None even after time out!");
var recvData = data.Value;
if (recvData.Address != address || recvData.Port != port)
throw new Exception("Receive Data From Wrong Board!");
var retPack = WebProtocol.RecvDataPackage.FromBytes(recvData.Data);
if (!retPack.IsSuccessful)
throw new Exception("Not RecvDataPackage!", retPack.Error);
return retPack.Value;
}
private void ReceiveHandler(IAsyncResult res)
{
var remoteEP = new IPEndPoint(IPAddress.Any, listenPort);
@ -210,16 +276,19 @@ public class UDPServer
Port = remotePort,
Data = bytes,
DateTime = nowtime,
HasRead = false,
});
logger.Trace("Receive data from old client");
}
else
{
udpData.Add(remoteAddress, new List<UDPData>([new UDPData(){
udpData.Add(remoteAddress, new List<UDPData>([new UDPData()
{
Address = remoteAddress,
Port = remotePort,
Data = bytes,
DateTime = nowtime,
HasRead = false,
}]));
logger.Trace("Receive data from new client");
}
@ -268,7 +337,7 @@ public class UDPServer
logger.Debug($"Receive Data from {remoteStr} at {nowtime.ToString()}:");
logger.Debug($"Original Data: {BitConverter.ToString(bytes).Replace("-", " ")}");
if (recvData.Length != 0) logger.Debug(recvData);
RecordAllData();
// RecordAllData();
listener.BeginReceive(new AsyncCallback(ReceiveHandler), null);

View File

@ -28,33 +28,44 @@ namespace WebProtocol
/// <summary> Package options which to send address to read or write </summary>
/// <example>
/// {
/// "burType":0,
/// "commandID":1,
/// }
/// </example>
public struct SendAddrPackOptions
public class SendAddrPackOptions
{
/// <summary> Package Burst Type </summary>
[JsonProperty("burstType")]
public BurstType burstType;
/// <example>1</example>
public byte commandID;
/// <summary> 标识写入还是读取 </summary>
/// <example> true </example>
public bool isWrite;
/// <summary> 突发长度0是32bits255是32bits x 256 </summary>
/// <example> 255 </example>
public byte burstLength;
/// <example> 0x10_00_00_00 </example>
public UInt32 address;
/// <summary>
/// 突发类型
/// </summary>
/// <example>0</example>
public BurstType BurstType { get; set; }
/// <summary>
/// Convert to Json String
/// 任务ID
/// </summary>
/// <returns> Json String </returns>
/// <example>1</example>
public byte CommandID { get; set; }
/// <summary>
/// 标识写入还是读取
/// </summary>
/// <example>true</example>
public bool IsWrite { get; set; }
/// <summary>
/// 突发长度0是32bits255是32bits x 256
/// </summary>
/// <example>255</example>
public byte BurstLength { get; set; }
/// <summary>
/// 目标地址
/// </summary>
/// <example>0</example>
public UInt32 Address { get; set; }
/// <summary>
/// 转换为Json格式字符串
/// </summary>
/// <returns>Json String</returns>
public override string ToString()
{
return JsonConvert.SerializeObject(this);
@ -62,7 +73,7 @@ namespace WebProtocol
}
/// <summary> Package Options which to receive from boards </summary>
public struct RecvPackOptions
public class RecvPackOptions
{
/// <summary> 数据包类型 </summary>
public enum PackType
@ -76,19 +87,26 @@ namespace WebProtocol
/// <summary>
/// 数据包类型
/// </summary>
public PackType type;
/// <example>0</example>
public PackType Type { get; set; }
/// <summary>
/// Task ID
/// </summary>
public byte commandID;
/// <example>0</example>
public byte CommandID { get; set; }
/// <summary>
/// Whether is succeed to finish command
/// </summary>
public bool isSuccess;
/// <example>true</example>
public bool IsSuccess { get; set; }
/// <summary>
/// Return Data
/// </summary>
public byte[]? data;
/// <example>[]</example>
public byte[]? Data { get; set; }
/// <summary>
/// Convert to Json String
@ -101,7 +119,7 @@ namespace WebProtocol
}
/// <summary> Server->FPGA 地址包 </summary>
public struct SendAddrPackage
public class SendAddrPackage
{
readonly byte sign = (byte)PackSign.SendAddr;
readonly byte commandType;
@ -115,12 +133,12 @@ namespace WebProtocol
/// <param name="opts"> 地址包选项 </param>
public SendAddrPackage(SendAddrPackOptions opts)
{
byte byteBurstType = Convert.ToByte((byte)opts.burstType << 6);
byte byteCommandID = Convert.ToByte((opts.commandID & 0x03) << 4);
byte byteIsWrite = (opts.isWrite ? (byte)0x01 : (byte)0x00);
byte byteBurstType = Convert.ToByte((byte)opts.BurstType << 6);
byte byteCommandID = Convert.ToByte((opts.CommandID & 0x03) << 4);
byte byteIsWrite = (opts.IsWrite ? (byte)0x01 : (byte)0x00);
this.commandType = Convert.ToByte(byteBurstType | byteCommandID | byteIsWrite);
this.burstLength = opts.burstLength;
this.address = opts.address;
this.burstLength = opts.BurstLength;
this.address = opts.Address;
}
/// <summary>
@ -178,12 +196,12 @@ namespace WebProtocol
/// <returns> 字符串 </returns>
public override string ToString()
{
SendAddrPackOptions opts;
opts.burstType = (BurstType)(commandType >> 6);
opts.commandID = Convert.ToByte((commandType >> 4) & 0b0011);
opts.isWrite = Convert.ToBoolean(commandType & 0x01);
opts.burstLength = burstLength;
opts.address = address;
var opts = new SendAddrPackOptions();
opts.BurstType = (BurstType)(commandType >> 6);
opts.CommandID = Convert.ToByte((commandType >> 4) & 0b0011);
opts.IsWrite = Convert.ToBoolean(commandType & 0x01);
opts.BurstLength = burstLength;
opts.Address = address;
return JsonConvert.SerializeObject(opts);
}
@ -287,16 +305,24 @@ namespace WebProtocol
{
get
{
RecvPackOptions opts;
opts.type = RecvPackOptions.PackType.ReadResp;
opts.commandID = commandID;
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? false : true);
opts.data = bodyData;
var opts = new RecvPackOptions();
opts.Type = RecvPackOptions.PackType.ReadResp;
opts.CommandID = commandID;
opts.IsSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? false : true);
opts.Data = bodyData;
return opts;
}
}
/// <summary>
/// 读取是否成功
/// </summary>
public bool IsSuccessful
{
get { return Convert.ToBoolean((resp >> 1) == 0b01 ? false : true); }
}
/// <summary>
/// 从字节数组构建读响应包
/// </summary>
@ -342,16 +368,24 @@ namespace WebProtocol
{
get
{
RecvPackOptions opts;
opts.type = RecvPackOptions.PackType.WriteResp;
opts.commandID = commandID;
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? false : true);
opts.data = null;
var opts = new RecvPackOptions();
opts.Type = RecvPackOptions.PackType.WriteResp;
opts.CommandID = commandID;
opts.IsSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? false : true);
opts.Data = null;
return opts;
}
}
/// <summary>
/// 写入是否成功
/// </summary>
public bool IsSuccessful
{
get { return Convert.ToBoolean((resp >> 1) == 0b01 ? false : true); }
}
/// <summary>
/// 从字节数组构建写响应包
/// </summary>