maybe fix bug: download bitstream failed
This commit is contained in:
		
							
								
								
									
										17
									
								
								.justfile
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								.justfile
									
									
									
									
									
								
							@@ -3,20 +3,35 @@
 | 
			
		||||
  pwd
 | 
			
		||||
  echo
 | 
			
		||||
 | 
			
		||||
# 清空构建文件
 | 
			
		||||
clean: 
 | 
			
		||||
  rm -rf "server/bin"
 | 
			
		||||
  rm -rf "server/obj"
 | 
			
		||||
  rm -rf "server.test/bin"
 | 
			
		||||
  rm -rf "server.test/obj"
 | 
			
		||||
  rm -rf "dist"
 | 
			
		||||
 | 
			
		||||
# 生成Restful API到网页客户端
 | 
			
		||||
gen-api:
 | 
			
		||||
  cd server && dotnet run &
 | 
			
		||||
  npx nswag openapi2tsclient /input:http://localhost:5000/swagger/v1/swagger.json /output:src/APIClient.ts
 | 
			
		||||
  pkill server
 | 
			
		||||
 | 
			
		||||
# 构建服务器,包含win与linux平台
 | 
			
		||||
[working-directory: "server"]
 | 
			
		||||
publish: _show-dir
 | 
			
		||||
build-server: _show-dir
 | 
			
		||||
  dotnet publish --self-contained false -t:PublishAllRids
 | 
			
		||||
 | 
			
		||||
# 运行服务器
 | 
			
		||||
[working-directory: "server"]
 | 
			
		||||
run-server: _show-dir
 | 
			
		||||
  dotnet run
 | 
			
		||||
 | 
			
		||||
# 运行网页客户端
 | 
			
		||||
run-web: 
 | 
			
		||||
  npm run dev
 | 
			
		||||
  
 | 
			
		||||
# 运行测试用例测试服务器
 | 
			
		||||
[working-directory: "server.test"]
 | 
			
		||||
test-server: _show-dir
 | 
			
		||||
  dotnet test --logger "console;verbosity=detailed"
 | 
			
		||||
 
 | 
			
		||||
@@ -251,46 +251,150 @@ public class JtagController : ControllerBase
 | 
			
		||||
        {
 | 
			
		||||
            // 读取文件
 | 
			
		||||
            var filePath = Directory.GetFiles(fileDir)[0];
 | 
			
		||||
            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];
 | 
			
		||||
            long totalBytesRead = 0;
 | 
			
		||||
 | 
			
		||||
            // 使用异步流读取文件
 | 
			
		||||
            using (var memoryStream = new MemoryStream())
 | 
			
		||||
            using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open))
 | 
			
		||||
            {
 | 
			
		||||
                int bytesRead;
 | 
			
		||||
                while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
 | 
			
		||||
                if (fileStream is null || fileStream.Length <= 0)
 | 
			
		||||
                    return TypedResults.BadRequest("Wrong bitstream, Please upload it again");
 | 
			
		||||
 | 
			
		||||
                // 定义缓冲区大小: 32KB
 | 
			
		||||
                byte[] buffer = new byte[32 * 1024];
 | 
			
		||||
                long totalBytesRead = 0;
 | 
			
		||||
 | 
			
		||||
                // 使用异步流读取文件
 | 
			
		||||
                using (var memoryStream = new MemoryStream())
 | 
			
		||||
                {
 | 
			
		||||
                    await memoryStream.WriteAsync(buffer, 0, bytesRead);
 | 
			
		||||
                    totalBytesRead += bytesRead;
 | 
			
		||||
                    int bytesRead;
 | 
			
		||||
                    while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        await memoryStream.WriteAsync(buffer, 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);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存)
 | 
			
		||||
                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 Log : ControllerBase
 | 
			
		||||
{
 | 
			
		||||
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
 | 
			
		||||
 | 
			
		||||
    private readonly string _logFilePath = Directory.GetFiles(Directory.GetCurrentDirectory())[0];
 | 
			
		||||
 | 
			
		||||
    [HttpGet]
 | 
			
		||||
    public async Task<IActionResult> Index()
 | 
			
		||||
    {
 | 
			
		||||
        if (!System.IO.File.Exists(_logFilePath))
 | 
			
		||||
        {
 | 
			
		||||
            Problem("日志文件不存在");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 请求头
 | 
			
		||||
        Response.Headers.Add("Content-Type", "text/event-stream");
 | 
			
		||||
        Response.Headers.Add("Cache-Control", "no-cache");
 | 
			
		||||
        Response.Headers.Add("Connection", "keep-alive");
 | 
			
		||||
 | 
			
		||||
        long position = 0;
 | 
			
		||||
        while (!HttpContext.RequestAborted.IsCancellationRequested)
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                if (System.IO.File.Exists(_logFilePath))
 | 
			
		||||
                {
 | 
			
		||||
                    using (var stream = new FileStream(_logFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
 | 
			
		||||
                    {
 | 
			
		||||
                        stream.Position = position;
 | 
			
		||||
                        using (var reader = new StreamReader(stream))
 | 
			
		||||
                        {
 | 
			
		||||
                            string? line;
 | 
			
		||||
                            while ((line = await reader.ReadLineAsync()) != null)
 | 
			
		||||
                            {
 | 
			
		||||
                                // await WriteEvent(line);
 | 
			
		||||
                                await Response.WriteAsync($"data: {line}\n\n");
 | 
			
		||||
                                await Response.Body.FlushAsync();
 | 
			
		||||
                                position = stream.Position;
 | 
			
		||||
                            }
 | 
			
		||||
                            if (line is null) break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    await WriteEvent("日志文件被删除");
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await WriteEvent($"错误: {ex.Message}");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await Task.Delay(1000, HttpContext.RequestAborted); // 每秒检查一次
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 结束
 | 
			
		||||
        return new EmptyResult();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private async Task WriteEvent(string message)
 | 
			
		||||
    {
 | 
			
		||||
        await Response.WriteAsync($"data: {message}\n\n");
 | 
			
		||||
        await Response.Body.FlushAsync();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [HttpGet("example")]
 | 
			
		||||
    public async Task<IActionResult> SseExample()
 | 
			
		||||
    {
 | 
			
		||||
        // 请求头
 | 
			
		||||
        Response.Headers.Add("Content-Type", "text/event-stream");
 | 
			
		||||
        Response.Headers.Add("Cache-Control", "no-cache");
 | 
			
		||||
        Response.Headers.Add("Connection", "keep-alive");
 | 
			
		||||
 | 
			
		||||
        // 假设不断得到新数据
 | 
			
		||||
        for (int i = 0; i < 10000; i++)
 | 
			
		||||
        {
 | 
			
		||||
            // 每个数据参照 SSE 返回数据格式进行组装
 | 
			
		||||
            var content = "event: message\n"
 | 
			
		||||
                + "data: {\"color\":\"66ccff\"}\n\n";
 | 
			
		||||
 | 
			
		||||
            // 立刻写入响应
 | 
			
		||||
            await Response.WriteAsync(content);
 | 
			
		||||
            await Response.Body.FlushAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 结束
 | 
			
		||||
        return new EmptyResult();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -220,6 +220,8 @@ public class Jtag
 | 
			
		||||
{
 | 
			
		||||
    private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
 | 
			
		||||
 | 
			
		||||
    private const int CLOCK_FREQ = 50; // MHz
 | 
			
		||||
 | 
			
		||||
    readonly int timeout;
 | 
			
		||||
 | 
			
		||||
    readonly int port;
 | 
			
		||||
@@ -274,7 +276,7 @@ public class Jtag
 | 
			
		||||
        return Convert.ToUInt32(Common.Number.BytesToNumber(retPackOpts.Data).Value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, UInt32 data)
 | 
			
		||||
    public async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, UInt32 data, UInt32 delayMilliseconds = 0)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = false;
 | 
			
		||||
        var opts = new SendAddrPackOptions();
 | 
			
		||||
@@ -303,6 +305,9 @@ public class Jtag
 | 
			
		||||
        else if (!udpWriteAck.Value.IsSuccessful)
 | 
			
		||||
            return new(new Exception("Send address package failed"));
 | 
			
		||||
 | 
			
		||||
        // Delay some time before read register
 | 
			
		||||
        await Task.Delay(TimeSpan.FromMilliseconds(delayMilliseconds));
 | 
			
		||||
 | 
			
		||||
        // Read Jtag State Register
 | 
			
		||||
        opts.IsWrite = false;
 | 
			
		||||
        opts.Address = JtagAddr.STATE;
 | 
			
		||||
@@ -317,7 +322,7 @@ public class Jtag
 | 
			
		||||
        return udpDataResp.Value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, byte[] dataArray)
 | 
			
		||||
    async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, byte[] dataArray, UInt32 delayMilliseconds = 0)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = false;
 | 
			
		||||
        var opts = new SendAddrPackOptions();
 | 
			
		||||
@@ -334,20 +339,21 @@ public class Jtag
 | 
			
		||||
        var writeTimes = dataArray.Length / (256 * (32 / 8)) + 1;
 | 
			
		||||
        for (var i = 0; i < writeTimes; i++)
 | 
			
		||||
        {
 | 
			
		||||
            // Sperate Data Array
 | 
			
		||||
            var isLastData = i == writeTimes - 1;
 | 
			
		||||
            var sendDataArray =
 | 
			
		||||
                isLastData ?
 | 
			
		||||
                dataArray[(i * (256 * (32 / 8)))..] :
 | 
			
		||||
                dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)))];
 | 
			
		||||
 | 
			
		||||
            // Write Jtag State Register
 | 
			
		||||
            opts.IsWrite = true;
 | 
			
		||||
            opts.BurstLength = isLastData ? (byte)(dataArray.Length - i * (256 * (32 / 8)) - 1) : (byte)255;
 | 
			
		||||
            opts.BurstLength = ((byte)(sendDataArray.Length / 4 - 1));
 | 
			
		||||
            ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
 | 
			
		||||
            if (!ret) return new(new Exception("Send 1st address package failed!"));
 | 
			
		||||
 | 
			
		||||
            // Send Data Package
 | 
			
		||||
            ret = await UDPClientPool.SendDataPackAsync(ep,
 | 
			
		||||
                    new SendDataPackage(
 | 
			
		||||
                        isLastData ?
 | 
			
		||||
                        dataArray[(i * (256 * (32 / 8)))..] :
 | 
			
		||||
                        dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)) - 1)]
 | 
			
		||||
                    )
 | 
			
		||||
                );
 | 
			
		||||
            ret = await UDPClientPool.SendDataPackAsync(ep, new SendDataPackage(sendDataArray));
 | 
			
		||||
            if (!ret) return new(new Exception("Send data package failed!"));
 | 
			
		||||
 | 
			
		||||
            // Wait for Write Ack
 | 
			
		||||
@@ -357,6 +363,9 @@ public class Jtag
 | 
			
		||||
                return new(new Exception("Send address package failed"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Delay some time before read register
 | 
			
		||||
        await Task.Delay(TimeSpan.FromMilliseconds(delayMilliseconds));
 | 
			
		||||
 | 
			
		||||
        // Read Jtag State Register
 | 
			
		||||
        opts.IsWrite = false;
 | 
			
		||||
        opts.BurstLength = 0;
 | 
			
		||||
@@ -373,10 +382,10 @@ public class Jtag
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<bool>> WriteFIFO
 | 
			
		||||
        (UInt32 devAddr, UInt32 data, UInt32 result, UInt32 resultMask = 0xFF_FF_FF_FF)
 | 
			
		||||
        (UInt32 devAddr, UInt32 data, UInt32 result, UInt32 resultMask = 0xFF_FF_FF_FF, UInt32 delayMilliseconds = 0)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = false;
 | 
			
		||||
        var retPack = await WriteFIFO(devAddr, data);
 | 
			
		||||
        var retPack = await WriteFIFO(devAddr, data, delayMilliseconds);
 | 
			
		||||
        if (!retPack.IsSuccessful) return new(retPack.Error);
 | 
			
		||||
 | 
			
		||||
        if (retPack.Value.Options.Data is null)
 | 
			
		||||
@@ -394,10 +403,10 @@ public class Jtag
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<bool>> WriteFIFO
 | 
			
		||||
        (UInt32 devAddr, byte[] data, UInt32 result, UInt32 resultMask = 0xFF_FF_FF_FF)
 | 
			
		||||
        (UInt32 devAddr, byte[] data, UInt32 result, UInt32 resultMask = 0xFF_FF_FF_FF, UInt32 delayMilliseconds = 0)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = false;
 | 
			
		||||
        var retPack = await WriteFIFO(devAddr, data);
 | 
			
		||||
        var retPack = await WriteFIFO(devAddr, data, delayMilliseconds);
 | 
			
		||||
 | 
			
		||||
        if (retPack.Value.Options.Data is null)
 | 
			
		||||
            return new(new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}"));
 | 
			
		||||
@@ -413,6 +422,45 @@ public class Jtag
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<bool>> WaitForWriteFIFO
 | 
			
		||||
        (UInt32 devAddr, byte[] data, UInt32 result,
 | 
			
		||||
         UInt32 resultMask = 0xFF_FF_FF_FF, UInt32 timeout = 10_000, UInt32 cycle = 500)
 | 
			
		||||
    {
 | 
			
		||||
        {
 | 
			
		||||
            var wrRet = await WriteFIFO(devAddr, data, result, resultMask);
 | 
			
		||||
 | 
			
		||||
            if (!wrRet.IsSuccessful) return new(wrRet.Error);
 | 
			
		||||
            if (wrRet.Value) return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Wait some time
 | 
			
		||||
        var ret = false;
 | 
			
		||||
        var startTime = DateTime.Now;
 | 
			
		||||
        var isTimeout = false;
 | 
			
		||||
        var timeleft = TimeSpan.FromMilliseconds(timeout);
 | 
			
		||||
        while (!isTimeout)
 | 
			
		||||
        {
 | 
			
		||||
            // Check whether timeout
 | 
			
		||||
            var elapsed = DateTime.Now - startTime;
 | 
			
		||||
            isTimeout = elapsed >= TimeSpan.FromMilliseconds(timeout);
 | 
			
		||||
            if (isTimeout) break;
 | 
			
		||||
            timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
 | 
			
		||||
 | 
			
		||||
            // Check FIFO
 | 
			
		||||
            var retPack = await ReadFIFO(JtagAddr.STATE);
 | 
			
		||||
            if (Common.Number.BitsCheck(retPack.Value, result, resultMask))
 | 
			
		||||
            {
 | 
			
		||||
                ret = true;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Wait
 | 
			
		||||
            await Task.Delay(TimeSpan.FromMilliseconds(cycle));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<bool>> ClearAllRegisters()
 | 
			
		||||
    {
 | 
			
		||||
@@ -447,7 +495,7 @@ public class Jtag
 | 
			
		||||
        return await WriteFIFO(
 | 
			
		||||
                JtagAddr.WRITE_CMD,
 | 
			
		||||
                Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_IDLE_DELAY, JtagCmd.LEN_CMD_JTAG, milliseconds, 28).Value,
 | 
			
		||||
                0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
 | 
			
		||||
                0x01_00_00_00, JtagState.CMD_EXEC_FINISH, (milliseconds / CLOCK_FREQ) + 100);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<bool>> ExecRDCmd(uint command)
 | 
			
		||||
@@ -472,7 +520,7 @@ public class Jtag
 | 
			
		||||
        return await ClearWriteDataReg();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<bool>> LoadDRCareInput(byte[] bytesArray)
 | 
			
		||||
    async ValueTask<Result<bool>> LoadDRCareInput(byte[] bytesArray, UInt32 timeout = 10_000, UInt32 cycle = 500)
 | 
			
		||||
    {
 | 
			
		||||
        var bytesLen = ((uint)(bytesArray.Length * 8));
 | 
			
		||||
        if (bytesLen > Math.Pow(2, 28)) return new(new Exception("Length is over 2^(28 - 3)"));
 | 
			
		||||
@@ -481,13 +529,17 @@ public class Jtag
 | 
			
		||||
            var ret = await WriteFIFO(
 | 
			
		||||
                    JtagAddr.WRITE_CMD,
 | 
			
		||||
                    Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREI, JtagCmd.LEN_CMD_JTAG, bytesLen, 28).Value,
 | 
			
		||||
                    0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
 | 
			
		||||
                    0, 0);
 | 
			
		||||
 | 
			
		||||
            if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
            else if (!ret.Value) return new(new Exception("Write CMD_JTAG_LOAD_DR_CAREI Failed"));
 | 
			
		||||
        }
 | 
			
		||||
        {
 | 
			
		||||
            var ret = await WriteFIFO(JtagAddr.WRITE_DATA, bytesArray, 0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
 | 
			
		||||
            var ret = await WaitForWriteFIFO(
 | 
			
		||||
                JtagAddr.WRITE_DATA,
 | 
			
		||||
                bytesArray, 0x01_00_00_00,
 | 
			
		||||
                JtagState.CMD_EXEC_FINISH,
 | 
			
		||||
                timeout, cycle);
 | 
			
		||||
 | 
			
		||||
            if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
            else if (!ret.Value) return new(new Exception("Write Data Failed"));
 | 
			
		||||
 
 | 
			
		||||
@@ -116,6 +116,7 @@ public class UDPServer
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ipAddr"> 目标IP地址 </param>
 | 
			
		||||
    /// <param name="timeout">超时时间</param>
 | 
			
		||||
    /// <param name="cycle">延迟时间</param>
 | 
			
		||||
    /// <param name="callerName">调用函数名称</param>
 | 
			
		||||
    /// <param name="callerLineNum">调用函数位置</param>
 | 
			
		||||
    /// <returns>
 | 
			
		||||
@@ -124,7 +125,7 @@ public class UDPServer
 | 
			
		||||
    /// Optional 存在时,为最先收到的数据
 | 
			
		||||
    /// </returns>
 | 
			
		||||
    public async ValueTask<Optional<UDPData>> FindDataAsync(
 | 
			
		||||
         string ipAddr, int timeout = 1000,
 | 
			
		||||
         string ipAddr, int timeout = 1000, int cycle = 0,
 | 
			
		||||
         [CallerMemberName] string callerName = "",
 | 
			
		||||
         [CallerLineNumber] int callerLineNum = 0)
 | 
			
		||||
    {
 | 
			
		||||
@@ -153,6 +154,8 @@ public class UDPServer
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await Task.Delay(cycle);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (data is null)
 | 
			
		||||
@@ -171,8 +174,9 @@ public class UDPServer
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ipAddr">IP地址</param>
 | 
			
		||||
    /// <param name="timeout">超时时间</param>
 | 
			
		||||
    /// <param name="cycle">延迟时间</param>
 | 
			
		||||
    /// <returns>数据列表</returns>
 | 
			
		||||
    public async ValueTask<Optional<List<UDPData>>> GetDataArrayAsync(string ipAddr, int timeout = 1000)
 | 
			
		||||
    public async ValueTask<Optional<List<UDPData>>> GetDataArrayAsync(string ipAddr, int timeout = 1000, int cycle = 0)
 | 
			
		||||
    {
 | 
			
		||||
        List<UDPData>? data = null;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,10 +20,10 @@ namespace WebProtocol
 | 
			
		||||
    /// <summary> Package Burst Type </summary>
 | 
			
		||||
    public enum BurstType
 | 
			
		||||
    {
 | 
			
		||||
        /// <summary> Extended Type </summary>
 | 
			
		||||
        ExtendBurst = 0b00,
 | 
			
		||||
        /// <summary> Fixed Type </summary>
 | 
			
		||||
        FixedBurst = 0b01,
 | 
			
		||||
        FixedBurst = 0b00,
 | 
			
		||||
        /// <summary> Extended Type </summary>
 | 
			
		||||
        ExtendBurst = 0b01,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user