Compare commits
3 Commits
6526203981
...
5ea541ef4b
Author | SHA1 | Date |
---|---|---|
|
5ea541ef4b | |
|
7f99a5be24 | |
|
0fb5a16b8e |
|
@ -3,6 +3,12 @@
|
||||||
pwd
|
pwd
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf "server/bin"
|
||||||
|
rm -rf "server/obj"
|
||||||
|
rm -rf "server.test/bin"
|
||||||
|
rm -rf "server.test/obj"
|
||||||
|
|
||||||
[working-directory: "server"]
|
[working-directory: "server"]
|
||||||
publish: _show-dir
|
publish: _show-dir
|
||||||
dotnet publish --self-contained false -t:PublishAllRids
|
dotnet publish --self-contained false -t:PublishAllRids
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"daisyui": "^5.0.0",
|
"daisyui": "^5.0.0",
|
||||||
"npm-run-all2": "^7.0.2",
|
"npm-run-all2": "^7.0.2",
|
||||||
|
"nswag": "^14.3.0",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"typescript": "~5.7.3",
|
"typescript": "~5.7.3",
|
||||||
|
@ -3172,6 +3173,19 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nswag": {
|
||||||
|
"version": "14.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nswag/-/nswag-14.3.0.tgz",
|
||||||
|
"integrity": "sha512-6/vGw9VtCBn788WFyPLwO4TWxZghDy+KSELjowXt12ZAu/0n3lLfQnJ4ws4rbXrO2Jrv0Tm3uzIfYNatrrs8bQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"nswag": "bin/nswag.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"npm": ">=3.10.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/open": {
|
"node_modules/open": {
|
||||||
"version": "10.1.1",
|
"version": "10.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/open/-/open-10.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/open/-/open-10.1.1.tgz",
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "fpga-weblab",
|
"name": "fpga-weblab",
|
||||||
"version": "0.0.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./server/index.ts",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "run-p type-check \"build-only {@}\" --",
|
"build": "run-p type-check \"build-only {@}\" --",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"build-only": "vite build",
|
"build-only": "vite build",
|
||||||
"type-check": "vue-tsc --build",
|
"type-check": "vue-tsc --build",
|
||||||
"server": "run --watch ./server/index.ts"
|
"pregen-api": "cd server && dotnet run &",
|
||||||
|
"gen-api": "npx nswag openapi2tsclient /input:http://localhost:5000/swagger/v1/swagger.json /output:src/APIClient.ts",
|
||||||
|
"postgen-api": "pkill server"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/lodash": "^4.17.16",
|
"@types/lodash": "^4.17.16",
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"daisyui": "^5.0.0",
|
"daisyui": "^5.0.0",
|
||||||
"npm-run-all2": "^7.0.2",
|
"npm-run-all2": "^7.0.2",
|
||||||
|
"nswag": "^14.3.0",
|
||||||
"postcss": "^8.5.3",
|
"postcss": "^8.5.3",
|
||||||
"tailwindcss": "^4.0.12",
|
"tailwindcss": "^4.0.12",
|
||||||
"typescript": "~5.7.3",
|
"typescript": "~5.7.3",
|
||||||
|
|
|
@ -18,10 +18,10 @@ namespace Common
|
||||||
{
|
{
|
||||||
if (length > 8)
|
if (length > 8)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(
|
return new(new ArgumentException(
|
||||||
"Unsigned long number can't over 8 bytes(64 bits).",
|
"Unsigned long number can't over 8 bytes(64 bits).",
|
||||||
nameof(length)
|
nameof(length)
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
var arr = new byte[length];
|
var arr = new byte[length];
|
||||||
|
@ -53,10 +53,10 @@ namespace Common
|
||||||
{
|
{
|
||||||
if (bytes.Length > 8)
|
if (bytes.Length > 8)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(
|
return new(new ArgumentException(
|
||||||
"Unsigned long number can't over 8 bytes(64 bits).",
|
"Unsigned long number can't over 8 bytes(64 bits).",
|
||||||
nameof(bytes)
|
nameof(bytes)
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong num = 0;
|
ulong num = 0;
|
||||||
|
@ -106,7 +106,7 @@ namespace Common
|
||||||
/// <returns>[TODO:return]</returns>
|
/// <returns>[TODO:return]</returns>
|
||||||
public static Result<ulong> MultiBitsToNumber(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len)
|
public static Result<ulong> MultiBitsToNumber(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len)
|
||||||
{
|
{
|
||||||
if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits");
|
if (bits1Len + bits2Len > 64) return new(new ArgumentException("Two Bits is more than 64 bits"));
|
||||||
|
|
||||||
ulong num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
|
ulong num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
|
||||||
return num;
|
return num;
|
||||||
|
@ -122,7 +122,7 @@ namespace Common
|
||||||
/// <returns>[TODO:return]</returns>
|
/// <returns>[TODO:return]</returns>
|
||||||
public static Result<uint> MultiBitsToNumber(uint bits1, uint bits1Len, uint bits2, uint bits2Len)
|
public static Result<uint> MultiBitsToNumber(uint bits1, uint bits1Len, uint bits2, uint bits2Len)
|
||||||
{
|
{
|
||||||
if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits");
|
if (bits1Len + bits2Len > 64) return new(new ArgumentException("Two Bits is more than 64 bits"));
|
||||||
|
|
||||||
uint num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
|
uint num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
|
||||||
return num;
|
return num;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Common;
|
using Common;
|
||||||
|
using DotNext;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using WebProtocol;
|
using WebProtocol;
|
||||||
|
@ -149,6 +150,7 @@ public class JtagController : ControllerBase
|
||||||
{
|
{
|
||||||
return "This is Jtag Controller";
|
return "This is Jtag Controller";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行一个Jtag命令
|
/// 执行一个Jtag命令
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -182,8 +184,16 @@ public class JtagController : ControllerBase
|
||||||
var jtagCtrl = new JtagClient.Jtag(address, port);
|
var jtagCtrl = new JtagClient.Jtag(address, port);
|
||||||
var ret = await jtagCtrl.ReadIDCode();
|
var ret = await jtagCtrl.ReadIDCode();
|
||||||
|
|
||||||
if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
|
if (ret.IsSuccessful)
|
||||||
else { return TypedResults.InternalServerError(ret.Error); }
|
{
|
||||||
|
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>
|
||||||
|
@ -217,7 +227,8 @@ public class JtagController : ControllerBase
|
||||||
await file.CopyToAsync(stream);
|
await file.CopyToAsync(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypedResults.Ok("文件上传成功");
|
logger.Info($"Device {address} Upload Bitstream Successfully");
|
||||||
|
return TypedResults.Ok("Bitstream Upload Successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -265,8 +276,16 @@ public class JtagController : ControllerBase
|
||||||
var jtagCtrl = new JtagClient.Jtag(address, port);
|
var jtagCtrl = new JtagClient.Jtag(address, port);
|
||||||
var ret = await jtagCtrl.DownloadBitstream(fileBytes);
|
var ret = await jtagCtrl.DownloadBitstream(fileBytes);
|
||||||
|
|
||||||
if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
|
if (ret.IsSuccessful)
|
||||||
else { return TypedResults.InternalServerError(ret.Error); }
|
{
|
||||||
|
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)
|
catch (Exception error)
|
||||||
|
|
|
@ -213,23 +213,34 @@ public static class JtagCmd
|
||||||
public const UInt32 CMD_JTAG_IDLE_DELAY = 0b0101;
|
public const UInt32 CMD_JTAG_IDLE_DELAY = 0b0101;
|
||||||
}
|
}
|
||||||
|
|
||||||
class Jtag
|
/// <summary>
|
||||||
|
/// Jtag控制器
|
||||||
|
/// </summary>
|
||||||
|
public class Jtag
|
||||||
{
|
{
|
||||||
|
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
readonly int timeout;
|
readonly int timeout;
|
||||||
|
|
||||||
readonly int port;
|
readonly int port;
|
||||||
readonly string address;
|
readonly string address;
|
||||||
private IPEndPoint ep;
|
private IPEndPoint ep;
|
||||||
|
|
||||||
public Jtag(string address, int port, int outTime = 2000)
|
/// <summary>
|
||||||
|
/// Jtag构造函数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="address">目标IP地址</param>
|
||||||
|
/// <param name="port">目标UDP端口</param>
|
||||||
|
/// <param name="timeout">超时时间</param>
|
||||||
|
public Jtag(string address, int port, int timeout = 2000)
|
||||||
{
|
{
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.ep = new IPEndPoint(IPAddress.Parse(address), port);
|
this.ep = new IPEndPoint(IPAddress.Parse(address), port);
|
||||||
this.timeout = outTime;
|
this.timeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<Result<uint>> ReadFIFO(uint devAddr)
|
async ValueTask<Result<uint>> ReadFIFO(uint devAddr)
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
var opts = new SendAddrPackOptions();
|
var opts = new SendAddrPackOptions();
|
||||||
|
@ -242,23 +253,23 @@ class Jtag
|
||||||
// Read Jtag State Register
|
// Read Jtag State Register
|
||||||
opts.IsWrite = false;
|
opts.IsWrite = false;
|
||||||
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
||||||
if (!ret) throw new Exception("Send Address Package Failed!");
|
if (!ret) return new(new Exception("Send Address Package Failed!"));
|
||||||
|
|
||||||
// Wait for Read Ack
|
// Wait for Read Ack
|
||||||
if (!MsgBus.IsRunning)
|
if (!MsgBus.IsRunning)
|
||||||
throw new Exception("Message Bus not Working!");
|
return new(new Exception("Message Bus not Working!"));
|
||||||
|
|
||||||
var retPack = await MsgBus.UDPServer.WaitForDataAsync(address, port);
|
var retPack = await MsgBus.UDPServer.WaitForDataAsync(address, port);
|
||||||
if (!retPack.IsSuccessful || !retPack.Value.IsSuccessful)
|
if (!retPack.IsSuccessful || !retPack.Value.IsSuccessful)
|
||||||
throw new Exception("Send address package failed");
|
return new(new Exception("Send address package failed"));
|
||||||
|
|
||||||
var retPackOpts = retPack.Value.Options;
|
var retPackOpts = retPack.Value.Options;
|
||||||
if (retPackOpts.Data is null)
|
if (retPackOpts.Data is null)
|
||||||
throw new Exception($"Data is Null, package: {retPackOpts.ToString()}");
|
return new(new Exception($"Data is Null, package: {retPackOpts.ToString()}"));
|
||||||
|
|
||||||
var retPackLen = retPackOpts.Data.Length;
|
var retPackLen = retPackOpts.Data.Length;
|
||||||
if (retPackLen != 4)
|
if (retPackLen != 4)
|
||||||
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
|
return new(new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"));
|
||||||
|
|
||||||
return Convert.ToUInt32(Common.Number.BytesToNumber(retPackOpts.Data).Value);
|
return Convert.ToUInt32(Common.Number.BytesToNumber(retPackOpts.Data).Value);
|
||||||
}
|
}
|
||||||
|
@ -277,36 +288,36 @@ class Jtag
|
||||||
// Write Jtag State Register
|
// Write Jtag State Register
|
||||||
opts.IsWrite = true;
|
opts.IsWrite = true;
|
||||||
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
||||||
if (!ret) throw new Exception("Send 1st address package failed!");
|
if (!ret) return new(new Exception("Send 1st address package failed!"));
|
||||||
// Send Data Package
|
// Send Data Package
|
||||||
ret = await UDPClientPool.SendDataPackAsync(ep,
|
ret = await UDPClientPool.SendDataPackAsync(ep,
|
||||||
new SendDataPackage(Common.Number.NumberToBytes(data, 4).Value));
|
new SendDataPackage(Common.Number.NumberToBytes(data, 4).Value));
|
||||||
if (!ret) throw new Exception("Send data package failed!");
|
if (!ret) return new(new Exception("Send data package failed!"));
|
||||||
|
|
||||||
// Check Msg Bus
|
// Check Msg Bus
|
||||||
if (!MsgBus.IsRunning)
|
if (!MsgBus.IsRunning)
|
||||||
throw new Exception("Message bus not working!");
|
return new(new Exception("Message bus not working!"));
|
||||||
// Wait for Write Ack
|
// Wait for Write Ack
|
||||||
var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(address, port);
|
var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(address, port);
|
||||||
if (!udpWriteAck.IsSuccessful) throw udpWriteAck.Error;
|
if (!udpWriteAck.IsSuccessful) return new(udpWriteAck.Error);
|
||||||
else if (!udpWriteAck.Value.IsSuccessful)
|
else if (!udpWriteAck.Value.IsSuccessful)
|
||||||
throw new Exception("Send address package failed");
|
return new(new Exception("Send address package failed"));
|
||||||
|
|
||||||
// Read Jtag State Register
|
// Read Jtag State Register
|
||||||
opts.IsWrite = false;
|
opts.IsWrite = false;
|
||||||
opts.Address = JtagAddr.STATE;
|
opts.Address = JtagAddr.STATE;
|
||||||
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
||||||
if (!ret) throw new Exception("Send 2rd Address Package Failed!");
|
if (!ret) return new(new Exception("Send 2rd Address Package Failed!"));
|
||||||
// Wait for Read Data
|
// Wait for Read Data
|
||||||
var udpDataResp = await MsgBus.UDPServer.WaitForDataAsync(address, port);
|
var udpDataResp = await MsgBus.UDPServer.WaitForDataAsync(address, port);
|
||||||
if (!udpDataResp.IsSuccessful) throw udpDataResp.Error;
|
if (!udpDataResp.IsSuccessful) return new(udpDataResp.Error);
|
||||||
else if (!udpDataResp.Value.IsSuccessful)
|
else if (!udpDataResp.Value.IsSuccessful)
|
||||||
throw new Exception("Send address package failed");
|
return new(new Exception("Send address package failed"));
|
||||||
|
|
||||||
return udpDataResp.Value;
|
return udpDataResp.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, byte[] dataArray)
|
async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, byte[] dataArray)
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
var opts = new SendAddrPackOptions();
|
var opts = new SendAddrPackOptions();
|
||||||
|
@ -318,7 +329,7 @@ class Jtag
|
||||||
|
|
||||||
// Check Msg Bus
|
// Check Msg Bus
|
||||||
if (!MsgBus.IsRunning)
|
if (!MsgBus.IsRunning)
|
||||||
throw new Exception("Message bus not working!");
|
return new(new Exception("Message bus not working!"));
|
||||||
|
|
||||||
var writeTimes = dataArray.Length / (256 * (32 / 8)) + 1;
|
var writeTimes = dataArray.Length / (256 * (32 / 8)) + 1;
|
||||||
for (var i = 0; i < writeTimes; i++)
|
for (var i = 0; i < writeTimes; i++)
|
||||||
|
@ -328,7 +339,7 @@ class Jtag
|
||||||
opts.IsWrite = true;
|
opts.IsWrite = true;
|
||||||
opts.BurstLength = isLastData ? (byte)(dataArray.Length - i * (256 * (32 / 8)) - 1) : (byte)255;
|
opts.BurstLength = isLastData ? (byte)(dataArray.Length - i * (256 * (32 / 8)) - 1) : (byte)255;
|
||||||
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
||||||
if (!ret) throw new Exception("Send 1st address package failed!");
|
if (!ret) return new(new Exception("Send 1st address package failed!"));
|
||||||
// Send Data Package
|
// Send Data Package
|
||||||
ret = await UDPClientPool.SendDataPackAsync(ep,
|
ret = await UDPClientPool.SendDataPackAsync(ep,
|
||||||
new SendDataPackage(
|
new SendDataPackage(
|
||||||
|
@ -337,13 +348,13 @@ class Jtag
|
||||||
dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)) - 1)]
|
dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)) - 1)]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (!ret) throw new Exception("Send data package failed!");
|
if (!ret) return new(new Exception("Send data package failed!"));
|
||||||
|
|
||||||
// Wait for Write Ack
|
// Wait for Write Ack
|
||||||
var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(address, port);
|
var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(address, port);
|
||||||
if (!udpWriteAck.IsSuccessful) throw udpWriteAck.Error;
|
if (!udpWriteAck.IsSuccessful) return new(udpWriteAck.Error);
|
||||||
else if (!udpWriteAck.Value.IsSuccessful)
|
else if (!udpWriteAck.Value.IsSuccessful)
|
||||||
throw new Exception("Send address package failed");
|
return new(new Exception("Send address package failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read Jtag State Register
|
// Read Jtag State Register
|
||||||
|
@ -351,29 +362,29 @@ class Jtag
|
||||||
opts.BurstLength = 0;
|
opts.BurstLength = 0;
|
||||||
opts.Address = JtagAddr.STATE;
|
opts.Address = JtagAddr.STATE;
|
||||||
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
||||||
if (!ret) throw new Exception("Send 2rd Address Package Failed!");
|
if (!ret) return new(new Exception("Send 2rd Address Package Failed!"));
|
||||||
// Wait for Read Data
|
// Wait for Read Data
|
||||||
var udpDataResp = await MsgBus.UDPServer.WaitForDataAsync(address, port);
|
var udpDataResp = await MsgBus.UDPServer.WaitForDataAsync(address, port);
|
||||||
if (!udpDataResp.IsSuccessful) throw udpDataResp.Error;
|
if (!udpDataResp.IsSuccessful) return new(udpDataResp.Error);
|
||||||
else if (!udpDataResp.Value.IsSuccessful)
|
else if (!udpDataResp.Value.IsSuccessful)
|
||||||
throw new Exception("Send address package failed");
|
return new(new Exception("Send address package failed"));
|
||||||
|
|
||||||
return udpDataResp.Value;
|
return udpDataResp.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<Result<bool>> WriteFIFO
|
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)
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
var retPack = await WriteFIFO(devAddr, data);
|
var retPack = await WriteFIFO(devAddr, data);
|
||||||
if (!retPack.IsSuccessful) throw retPack.Error;
|
if (!retPack.IsSuccessful) return new(retPack.Error);
|
||||||
|
|
||||||
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()}");
|
return new(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)
|
if (retPackLen != 4)
|
||||||
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
|
return new(new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"));
|
||||||
|
|
||||||
if (Common.Number.BitsCheck(
|
if (Common.Number.BitsCheck(
|
||||||
Common.Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask))
|
Common.Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask))
|
||||||
|
@ -382,18 +393,18 @@ class Jtag
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<Result<bool>> WriteFIFO
|
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)
|
||||||
{
|
{
|
||||||
var ret = false;
|
var ret = false;
|
||||||
var retPack = await WriteFIFO(devAddr, data);
|
var retPack = await WriteFIFO(devAddr, data);
|
||||||
|
|
||||||
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()}");
|
return new(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)
|
if (retPackLen != 4)
|
||||||
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
|
return new(new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"));
|
||||||
|
|
||||||
if (Common.Number.BitsCheck(
|
if (Common.Number.BitsCheck(
|
||||||
Common.Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask))
|
Common.Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask))
|
||||||
|
@ -431,7 +442,7 @@ class Jtag
|
||||||
|
|
||||||
async ValueTask<Result<bool>> IdleDelay(UInt32 milliseconds)
|
async ValueTask<Result<bool>> IdleDelay(UInt32 milliseconds)
|
||||||
{
|
{
|
||||||
if (milliseconds > Math.Pow(2, 28)) throw new Exception("Timespan is over 2^28 milliseconds");
|
if (milliseconds > Math.Pow(2, 28)) return new(new Exception("Timespan is over 2^28 milliseconds"));
|
||||||
|
|
||||||
return await WriteFIFO(
|
return await WriteFIFO(
|
||||||
JtagAddr.WRITE_CMD,
|
JtagAddr.WRITE_CMD,
|
||||||
|
@ -446,8 +457,8 @@ class Jtag
|
||||||
JtagAddr.WRITE_DATA,
|
JtagAddr.WRITE_DATA,
|
||||||
Common.Number.MultiBitsToNumber(0, 22, command, JtagCmd.LEN_JTAG_DR).Value, 0, 0);
|
Common.Number.MultiBitsToNumber(0, 22, command, JtagCmd.LEN_JTAG_DR).Value, 0, 0);
|
||||||
|
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Write JTAG_DR_IDCODE Failed");
|
else if (!ret.Value) return new(new Exception("Write JTAG_DR_IDCODE Failed"));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
var ret = await WriteFIFO(
|
var ret = await WriteFIFO(
|
||||||
|
@ -455,8 +466,8 @@ class Jtag
|
||||||
Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_IR, JtagCmd.LEN_CMD_JTAG, 10, 28).Value,
|
Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_IR, JtagCmd.LEN_CMD_JTAG, 10, 28).Value,
|
||||||
0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
|
0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
|
||||||
|
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Write CMD_JTAG_LOAD_IR Failed");
|
else if (!ret.Value) return new(new Exception("Write CMD_JTAG_LOAD_IR Failed"));
|
||||||
}
|
}
|
||||||
return await ClearWriteDataReg();
|
return await ClearWriteDataReg();
|
||||||
}
|
}
|
||||||
|
@ -464,7 +475,7 @@ class Jtag
|
||||||
async ValueTask<Result<bool>> LoadDRCareInput(byte[] bytesArray)
|
async ValueTask<Result<bool>> LoadDRCareInput(byte[] bytesArray)
|
||||||
{
|
{
|
||||||
var bytesLen = ((uint)(bytesArray.Length * 8));
|
var bytesLen = ((uint)(bytesArray.Length * 8));
|
||||||
if (bytesLen > Math.Pow(2, 28)) throw new Exception("Length is over 2^(28 - 3)");
|
if (bytesLen > Math.Pow(2, 28)) return new(new Exception("Length is over 2^(28 - 3)"));
|
||||||
|
|
||||||
{
|
{
|
||||||
var ret = await WriteFIFO(
|
var ret = await WriteFIFO(
|
||||||
|
@ -472,21 +483,21 @@ class Jtag
|
||||||
Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREI, JtagCmd.LEN_CMD_JTAG, bytesLen, 28).Value,
|
Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREI, JtagCmd.LEN_CMD_JTAG, bytesLen, 28).Value,
|
||||||
0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
|
0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
|
||||||
|
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Write CMD_JTAG_LOAD_DR_CAREI Failed");
|
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 WriteFIFO(JtagAddr.WRITE_DATA, bytesArray, 0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
|
||||||
|
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Write Data Failed");
|
else if (!ret.Value) return new(new Exception("Write Data Failed"));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async ValueTask<Result<UInt32>> LoadDRCareOutput(UInt32 bytesLen)
|
async ValueTask<Result<UInt32>> LoadDRCareOutput(UInt32 bytesLen)
|
||||||
{
|
{
|
||||||
if (bytesLen > Math.Pow(2, 28)) throw new Exception("Length is over 2^(28 - 3)");
|
if (bytesLen > Math.Pow(2, 28)) return new(new Exception("Length is over 2^(28 - 3)"));
|
||||||
|
|
||||||
var ret = await WriteFIFO(
|
var ret = await WriteFIFO(
|
||||||
JtagAddr.WRITE_CMD,
|
JtagAddr.WRITE_CMD,
|
||||||
|
@ -496,7 +507,7 @@ class Jtag
|
||||||
if (ret.Value)
|
if (ret.Value)
|
||||||
return await ReadFIFO(JtagAddr.READ_DATA);
|
return await ReadFIFO(JtagAddr.READ_DATA);
|
||||||
else
|
else
|
||||||
throw new Exception("LoadDRCareo Failed!");
|
return new(new Exception("LoadDRCareo Failed!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async ValueTask<Result<uint>> ReadIDCode()
|
public async ValueTask<Result<uint>> ReadIDCode()
|
||||||
|
@ -504,28 +515,30 @@ class Jtag
|
||||||
// Clear Data
|
// Clear Data
|
||||||
await MsgBus.UDPServer.ClearUDPData(this.address);
|
await MsgBus.UDPServer.ClearUDPData(this.address);
|
||||||
|
|
||||||
|
logger.Trace($"Clear up udp server {this.address} receive data");
|
||||||
|
|
||||||
Result<bool> ret;
|
Result<bool> ret;
|
||||||
|
|
||||||
ret = await ClearAllRegisters();
|
ret = await ClearAllRegisters();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Clear All Registers Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Clear All Registers Failed"));
|
||||||
|
|
||||||
ret = await RunTest();
|
ret = await RunTest();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
|
||||||
|
|
||||||
ret = await ExecRDCmd(JtagCmd.JTAG_DR_IDCODE);
|
ret = await ExecRDCmd(JtagCmd.JTAG_DR_IDCODE);
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_IDCODE Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_IDCODE Failed"));
|
||||||
|
|
||||||
ret = await ClearWriteDataReg();
|
ret = await ClearWriteDataReg();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Clear Write Registers Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Clear Write Registers Failed"));
|
||||||
|
|
||||||
var retData = await LoadDRCareOutput(4);
|
var retData = await LoadDRCareOutput(4);
|
||||||
if (!retData.IsSuccessful)
|
if (!retData.IsSuccessful)
|
||||||
{
|
{
|
||||||
throw new Exception("Get ID Code Failed");
|
return new(new Exception("Get ID Code Failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return retData.Value;
|
return retData.Value;
|
||||||
|
@ -536,66 +549,66 @@ class Jtag
|
||||||
// Clear Data
|
// Clear Data
|
||||||
await MsgBus.UDPServer.ClearUDPData(this.address);
|
await MsgBus.UDPServer.ClearUDPData(this.address);
|
||||||
|
|
||||||
|
logger.Trace($"Clear up udp server {this.address} receive data");
|
||||||
|
|
||||||
Result<bool> ret;
|
Result<bool> ret;
|
||||||
|
|
||||||
ret = await CloseTest();
|
ret = await CloseTest();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Close Test Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
|
||||||
|
|
||||||
|
|
||||||
ret = await RunTest();
|
ret = await RunTest();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
|
||||||
|
|
||||||
|
logger.Trace("Jtag initialize");
|
||||||
|
|
||||||
ret = await ExecRDCmd(JtagCmd.JTAG_DR_JRST);
|
ret = await ExecRDCmd(JtagCmd.JTAG_DR_JRST);
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_JRST Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_JRST Failed"));
|
||||||
|
|
||||||
|
|
||||||
ret = await RunTest();
|
ret = await RunTest();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
|
||||||
|
|
||||||
|
|
||||||
ret = await ExecRDCmd(JtagCmd.JTAG_DR_CFGI);
|
ret = await ExecRDCmd(JtagCmd.JTAG_DR_CFGI);
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_CFGI Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_CFGI Failed"));
|
||||||
|
|
||||||
|
logger.Trace("Jtag ready to write bitstream");
|
||||||
|
|
||||||
ret = await IdleDelay(75000);
|
ret = await IdleDelay(75000);
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag IDLE Delay Failed");
|
else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
|
||||||
|
|
||||||
|
|
||||||
ret = await LoadDRCareInput(bitstream);
|
ret = await LoadDRCareInput(bitstream);
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Load Data Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Load Data Failed"));
|
||||||
|
|
||||||
|
logger.Trace("Jtag write bitstream");
|
||||||
|
|
||||||
ret = await CloseTest();
|
ret = await CloseTest();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Close Test Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
|
||||||
|
|
||||||
|
|
||||||
ret = await RunTest();
|
ret = await RunTest();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
|
||||||
|
|
||||||
|
|
||||||
ret = await ExecRDCmd(JtagCmd.JTAG_DR_JWAKEUP);
|
ret = await ExecRDCmd(JtagCmd.JTAG_DR_JWAKEUP);
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_JWAKEUP Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_JWAKEUP Failed"));
|
||||||
|
|
||||||
|
logger.Trace("Jtag reset device");
|
||||||
|
|
||||||
ret = await IdleDelay(1000);
|
ret = await IdleDelay(1000);
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag IDLE Delay Failed");
|
else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
|
||||||
|
|
||||||
|
|
||||||
ret = await CloseTest();
|
ret = await CloseTest();
|
||||||
if (!ret.IsSuccessful) throw ret.Error;
|
if (!ret.IsSuccessful) return new(ret.Error);
|
||||||
else if (!ret.Value) throw new Exception("Jtag Close Test Failed");
|
else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
|
||||||
|
logger.Trace("Jtag download bitstream successfully");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ using System.Text;
|
||||||
using DotNext;
|
using DotNext;
|
||||||
using DotNext.Threading;
|
using DotNext.Threading;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using WebProtocol;
|
||||||
|
|
||||||
/// <summary> UDP接受数据包格式 </summary>
|
/// <summary> UDP接受数据包格式 </summary>
|
||||||
public class UDPData
|
public class UDPData
|
||||||
|
@ -58,9 +59,6 @@ public class UDPData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// UDP Server
|
|
||||||
/// </summary>
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UDP 服务器
|
/// UDP 服务器
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -80,6 +78,15 @@ public class UDPServer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsRunning { get { return isRunning; } }
|
public bool IsRunning { get { return isRunning; } }
|
||||||
|
|
||||||
|
/// <summary> UDP 服务器的错误代码 </summary>
|
||||||
|
public enum ErrorCode
|
||||||
|
{
|
||||||
|
Success = 0,
|
||||||
|
GetNoneAfterTimeout,
|
||||||
|
ResponseWrong,
|
||||||
|
NotRecvDataPackage,
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Construct a udp server with fixed port
|
/// Construct a udp server with fixed port
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -132,8 +139,9 @@ public class UDPServer
|
||||||
{
|
{
|
||||||
var elapsed = DateTime.Now - startTime;
|
var elapsed = DateTime.Now - startTime;
|
||||||
isTimeout = elapsed >= TimeSpan.FromMilliseconds(timeout);
|
isTimeout = elapsed >= TimeSpan.FromMilliseconds(timeout);
|
||||||
timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
|
if (isTimeout) break;
|
||||||
|
|
||||||
|
timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
|
||||||
using (await udpData.AcquireWriteLockAsync(timeleft))
|
using (await udpData.AcquireWriteLockAsync(timeleft))
|
||||||
{
|
{
|
||||||
if (udpData.ContainsKey(ipAddr) &&
|
if (udpData.ContainsKey(ipAddr) &&
|
||||||
|
@ -150,11 +158,11 @@ public class UDPServer
|
||||||
if (data is null)
|
if (data is null)
|
||||||
{
|
{
|
||||||
logger.Trace("Get nothing even after time out");
|
logger.Trace("Get nothing even after time out");
|
||||||
return Optional<UDPData>.None;
|
return new(null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Optional.Some((UDPData)data.DeepClone());
|
return new(data.DeepClone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,8 +183,9 @@ public class UDPServer
|
||||||
{
|
{
|
||||||
var elapsed = DateTime.Now - startTime;
|
var elapsed = DateTime.Now - startTime;
|
||||||
isTimeout = elapsed >= TimeSpan.FromMilliseconds(timeout);
|
isTimeout = elapsed >= TimeSpan.FromMilliseconds(timeout);
|
||||||
timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
|
if (isTimeout) break;
|
||||||
|
|
||||||
|
timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
|
||||||
using (await udpData.AcquireReadLockAsync(timeleft))
|
using (await udpData.AcquireReadLockAsync(timeleft))
|
||||||
{
|
{
|
||||||
if (udpData.ContainsKey(ipAddr) &&
|
if (udpData.ContainsKey(ipAddr) &&
|
||||||
|
@ -193,11 +202,11 @@ public class UDPServer
|
||||||
if (data is null)
|
if (data is null)
|
||||||
{
|
{
|
||||||
logger.Trace("Get nothing even after time out");
|
logger.Trace("Get nothing even after time out");
|
||||||
return Optional<List<UDPData>>.None;
|
return new(null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Optional.Some((List<UDPData>)data);
|
return new(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,15 +222,15 @@ public class UDPServer
|
||||||
{
|
{
|
||||||
var data = await FindDataAsync(address, timeout);
|
var data = await FindDataAsync(address, timeout);
|
||||||
if (!data.HasValue)
|
if (!data.HasValue)
|
||||||
throw new Exception("Get None even after time out!");
|
return new(new Exception("Get None even after time out!"));
|
||||||
|
|
||||||
var recvData = data.Value;
|
var recvData = data.Value;
|
||||||
if (recvData.Address != address || (port > 0 && recvData.Port != port))
|
if (recvData.Address != address || (port > 0 && recvData.Port != port))
|
||||||
throw new Exception("Receive Data From Wrong Board!");
|
return new(new Exception("Receive Data From Wrong Board!"));
|
||||||
|
|
||||||
var retPack = WebProtocol.RecvRespPackage.FromBytes(recvData.Data);
|
var retPack = WebProtocol.RecvRespPackage.FromBytes(recvData.Data);
|
||||||
if (!retPack.IsSuccessful)
|
if (!retPack.IsSuccessful)
|
||||||
throw new Exception("Not RecvDataPackage!", retPack.Error);
|
return new(new Exception("Not RecvDataPackage!", retPack.Error));
|
||||||
|
|
||||||
return retPack.Value;
|
return retPack.Value;
|
||||||
}
|
}
|
||||||
|
@ -233,20 +242,20 @@ public class UDPServer
|
||||||
/// <param name="port">UDP 端口</param>
|
/// <param name="port">UDP 端口</param>
|
||||||
/// <param name="timeout">超时时间范围</param>
|
/// <param name="timeout">超时时间范围</param>
|
||||||
/// <returns>接收数据包</returns>
|
/// <returns>接收数据包</returns>
|
||||||
public async ValueTask<Result<WebProtocol.RecvDataPackage>> WaitForDataAsync
|
public async ValueTask<Result<RecvDataPackage>> WaitForDataAsync
|
||||||
(string address, int port = -1, int timeout = 1000)
|
(string address, int port = -1, int timeout = 1000)
|
||||||
{
|
{
|
||||||
var data = await FindDataAsync(address, timeout);
|
var data = await FindDataAsync(address, timeout);
|
||||||
if (!data.HasValue)
|
if (!data.HasValue)
|
||||||
throw new Exception("Get None even after time out!");
|
return new(new Exception("Get None even after time out!"));
|
||||||
|
|
||||||
var recvData = data.Value;
|
var recvData = data.Value;
|
||||||
if (recvData.Address != address || (port >= 0 && recvData.Port != port))
|
if (recvData.Address != address || (port >= 0 && recvData.Port != port))
|
||||||
throw new Exception("Receive Data From Wrong Board!");
|
return new(new Exception("Receive Data From Wrong Board!"));
|
||||||
|
|
||||||
var retPack = WebProtocol.RecvDataPackage.FromBytes(recvData.Data);
|
var retPack = WebProtocol.RecvDataPackage.FromBytes(recvData.Data);
|
||||||
if (!retPack.IsSuccessful)
|
if (!retPack.IsSuccessful)
|
||||||
throw new Exception("Not RecvDataPackage!", retPack.Error);
|
return new(new Exception("Not RecvDataPackage!", retPack.Error));
|
||||||
|
|
||||||
return retPack.Value;
|
return retPack.Value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,18 +234,18 @@ namespace WebProtocol
|
||||||
{
|
{
|
||||||
if (bytes.Length != 8)
|
if (bytes.Length != 8)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(
|
return new(new ArgumentException(
|
||||||
"Bytes are not equal to 8 bytes.",
|
"Bytes are not equal to 8 bytes.",
|
||||||
nameof(bytes)
|
nameof(bytes)
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkSign && bytes[0] != (byte)PackSign.SendAddr)
|
if (checkSign && bytes[0] != (byte)PackSign.SendAddr)
|
||||||
{
|
{
|
||||||
throw new ArgumentException(
|
return new(new ArgumentException(
|
||||||
"The sign of bytes is not SendAddr Package, but you can disable it by set checkSign false.",
|
"The sign of bytes is not SendAddr Package, but you can disable it by set checkSign false.",
|
||||||
nameof(bytes)
|
nameof(bytes)
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
var address = Common.Number.BytesToNumber(bytes[4..]).Value;
|
var address = Common.Number.BytesToNumber(bytes[4..]).Value;
|
||||||
|
@ -377,10 +377,10 @@ namespace WebProtocol
|
||||||
public static Result<RecvDataPackage> FromBytes(byte[] bytes)
|
public static Result<RecvDataPackage> FromBytes(byte[] bytes)
|
||||||
{
|
{
|
||||||
if (bytes[0] != (byte)PackSign.RecvData)
|
if (bytes[0] != (byte)PackSign.RecvData)
|
||||||
throw new ArgumentException(
|
return new(new ArgumentException(
|
||||||
$"The sign of bytes is not RecvData Package, Sign: 0x{BitConverter.ToString([bytes[0]])}",
|
$"The sign of bytes is not RecvData Package, Sign: 0x{BitConverter.ToString([bytes[0]])}",
|
||||||
nameof(bytes)
|
nameof(bytes)
|
||||||
);
|
));
|
||||||
return new RecvDataPackage(bytes[1], bytes[2], bytes[4..]);
|
return new RecvDataPackage(bytes[1], bytes[2], bytes[4..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,10 +480,10 @@ namespace WebProtocol
|
||||||
public static Result<RecvRespPackage> FromBytes(byte[] bytes)
|
public static Result<RecvRespPackage> FromBytes(byte[] bytes)
|
||||||
{
|
{
|
||||||
if (bytes[0] != (byte)PackSign.RecvResp)
|
if (bytes[0] != (byte)PackSign.RecvResp)
|
||||||
throw new ArgumentException(
|
return new(new ArgumentException(
|
||||||
$"The sign of bytes is not RecvResp Package, Sign: 0x{BitConverter.ToString([bytes[0]])}",
|
$"The sign of bytes is not RecvResp Package, Sign: 0x{BitConverter.ToString([bytes[0]])}",
|
||||||
nameof(bytes)
|
nameof(bytes)
|
||||||
);
|
));
|
||||||
return new RecvRespPackage(bytes[1], bytes[2]);
|
return new RecvRespPackage(bytes[1], bytes[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,869 @@
|
||||||
|
//----------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// Generated using the NSwag toolchain v14.3.0.0 (NJsonSchema v11.2.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org)
|
||||||
|
// </auto-generated>
|
||||||
|
//----------------------
|
||||||
|
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
|
||||||
|
export class Client {
|
||||||
|
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
|
||||||
|
private baseUrl: string;
|
||||||
|
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
|
||||||
|
|
||||||
|
constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> }) {
|
||||||
|
this.http = http ? http : window as any;
|
||||||
|
this.baseUrl = baseUrl ?? "http://localhost:5000";
|
||||||
|
}
|
||||||
|
|
||||||
|
get(): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processGet(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processGet(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UDPClient {
|
||||||
|
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
|
||||||
|
private baseUrl: string;
|
||||||
|
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
|
||||||
|
|
||||||
|
constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> }) {
|
||||||
|
this.http = http ? http : window as any;
|
||||||
|
this.baseUrl = baseUrl ?? "http://localhost:5000";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面
|
||||||
|
*/
|
||||||
|
index(): Promise<string> {
|
||||||
|
let url_ = this.baseUrl + "/api/UDP";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processIndex(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processIndex(response: Response): Promise<string> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result200: any = null;
|
||||||
|
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
|
||||||
|
result200 = resultData200 !== undefined ? resultData200 : <any>null;
|
||||||
|
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<string>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送字符串
|
||||||
|
* @param address (optional) IPV4 或者 IPV6 地址
|
||||||
|
* @param port (optional) 设备端口号
|
||||||
|
* @param text (optional) 发送的文本
|
||||||
|
* @return 发送成功
|
||||||
|
*/
|
||||||
|
sendString(address: string | undefined, port: number | undefined, text: string | undefined): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/UDP/SendString?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
if (port === null)
|
||||||
|
throw new Error("The parameter 'port' cannot be null.");
|
||||||
|
else if (port !== undefined)
|
||||||
|
url_ += "port=" + encodeURIComponent("" + port) + "&";
|
||||||
|
if (text === null)
|
||||||
|
throw new Error("The parameter 'text' cannot be null.");
|
||||||
|
else if (text !== undefined)
|
||||||
|
url_ += "text=" + encodeURIComponent("" + text) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processSendString(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processSendString(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("\u53d1\u9001\u5931\u8d25", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送二进制数据
|
||||||
|
* @param address (optional) IPV4 或者 IPV6 地址
|
||||||
|
* @param port (optional) 设备端口号
|
||||||
|
* @param bytes (optional) 16进制文本
|
||||||
|
*/
|
||||||
|
sendBytes(address: string | undefined, port: number | undefined, bytes: string | undefined): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/UDP/SendBytes?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
if (port === null)
|
||||||
|
throw new Error("The parameter 'port' cannot be null.");
|
||||||
|
else if (port !== undefined)
|
||||||
|
url_ += "port=" + encodeURIComponent("" + port) + "&";
|
||||||
|
if (bytes === null)
|
||||||
|
throw new Error("The parameter 'bytes' cannot be null.");
|
||||||
|
else if (bytes !== undefined)
|
||||||
|
url_ += "bytes=" + encodeURIComponent("" + bytes) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processSendBytes(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processSendBytes(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送地址包
|
||||||
|
* @param address (optional) IP地址
|
||||||
|
* @param port (optional) UDP 端口号
|
||||||
|
* @param opts 地址包选项
|
||||||
|
*/
|
||||||
|
sendAddrPackage(address: string | undefined, port: number | undefined, opts: SendAddrPackOptions): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/UDP/SendAddrPackage?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
if (port === null)
|
||||||
|
throw new Error("The parameter 'port' cannot be null.");
|
||||||
|
else if (port !== undefined)
|
||||||
|
url_ += "port=" + encodeURIComponent("" + port) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
const content_ = JSON.stringify(opts);
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
body: content_,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processSendAddrPackage(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processSendAddrPackage(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送数据包
|
||||||
|
* @param address (optional) IP地址
|
||||||
|
* @param port (optional) UDP 端口号
|
||||||
|
* @param data (optional) 16进制数据
|
||||||
|
*/
|
||||||
|
sendDataPackage(address: string | undefined, port: number | undefined, data: string | undefined): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/UDP/SendDataPackage?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
if (port === null)
|
||||||
|
throw new Error("The parameter 'port' cannot be null.");
|
||||||
|
else if (port !== undefined)
|
||||||
|
url_ += "port=" + encodeURIComponent("" + port) + "&";
|
||||||
|
if (data === null)
|
||||||
|
throw new Error("The parameter 'data' cannot be null.");
|
||||||
|
else if (data !== undefined)
|
||||||
|
url_ += "data=" + encodeURIComponent("" + data) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processSendDataPackage(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processSendDataPackage(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指定IP地址接受的数据列表
|
||||||
|
* @param address (optional) IP地址
|
||||||
|
*/
|
||||||
|
getRecvDataArray(address: string | undefined): Promise<UDPData[]> {
|
||||||
|
let url_ = this.baseUrl + "/api/UDP/GetRecvDataArray?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processGetRecvDataArray(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processGetRecvDataArray(response: Response): Promise<UDPData[]> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result200: any = null;
|
||||||
|
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
|
||||||
|
if (Array.isArray(resultData200)) {
|
||||||
|
result200 = [] as any;
|
||||||
|
for (let item of resultData200)
|
||||||
|
result200!.push(UDPData.fromJS(item));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result200 = <any>null;
|
||||||
|
}
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<UDPData[]>(null as any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class JtagClient {
|
||||||
|
private http: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> };
|
||||||
|
private baseUrl: string;
|
||||||
|
protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined;
|
||||||
|
|
||||||
|
constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise<Response> }) {
|
||||||
|
this.http = http ? http : window as any;
|
||||||
|
this.baseUrl = baseUrl ?? "http://localhost:5000";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 页面
|
||||||
|
*/
|
||||||
|
index(): Promise<string> {
|
||||||
|
let url_ = this.baseUrl + "/api/Jtag";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processIndex(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processIndex(response: Response): Promise<string> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result200: any = null;
|
||||||
|
let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
|
||||||
|
result200 = resultData200 !== undefined ? resultData200 : <any>null;
|
||||||
|
|
||||||
|
return result200;
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<string>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行一个Jtag命令
|
||||||
|
* @param address (optional) 设备地址
|
||||||
|
* @param port (optional) 设备端口
|
||||||
|
* @param hexDevAddr (optional) 16进制设备目的地址(Jtag)
|
||||||
|
* @param hexCmd (optional) 16进制命令
|
||||||
|
*/
|
||||||
|
runCommand(address: string | undefined, port: number | undefined, hexDevAddr: string | undefined, hexCmd: string | undefined): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/Jtag/RunCommand?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
if (port === null)
|
||||||
|
throw new Error("The parameter 'port' cannot be null.");
|
||||||
|
else if (port !== undefined)
|
||||||
|
url_ += "port=" + encodeURIComponent("" + port) + "&";
|
||||||
|
if (hexDevAddr === null)
|
||||||
|
throw new Error("The parameter 'hexDevAddr' cannot be null.");
|
||||||
|
else if (hexDevAddr !== undefined)
|
||||||
|
url_ += "hexDevAddr=" + encodeURIComponent("" + hexDevAddr) + "&";
|
||||||
|
if (hexCmd === null)
|
||||||
|
throw new Error("The parameter 'hexCmd' cannot be null.");
|
||||||
|
else if (hexCmd !== undefined)
|
||||||
|
url_ += "hexCmd=" + encodeURIComponent("" + hexCmd) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processRunCommand(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processRunCommand(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Jtag ID Code
|
||||||
|
* @param address (optional) 设备地址
|
||||||
|
* @param port (optional) 设备端口
|
||||||
|
*/
|
||||||
|
getDeviceIDCode(address: string | undefined, port: number | undefined): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/Jtag/GetDeviceIDCode?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
if (port === null)
|
||||||
|
throw new Error("The parameter 'port' cannot be null.");
|
||||||
|
else if (port !== undefined)
|
||||||
|
url_ += "port=" + encodeURIComponent("" + port) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processGetDeviceIDCode(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processGetDeviceIDCode(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传比特流文件
|
||||||
|
* @param address (optional) 设备地址
|
||||||
|
* @param file (optional)
|
||||||
|
*/
|
||||||
|
uploadBitstream(address: string | undefined, file: FileParameter | null | undefined): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/Jtag/UploadBitstream?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
const content_ = new FormData();
|
||||||
|
if (file !== null && file !== undefined)
|
||||||
|
content_.append("file", file.data, file.fileName ? file.fileName : "file");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
body: content_,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processUploadBitstream(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processUploadBitstream(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 400) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result400: any = null;
|
||||||
|
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
|
||||||
|
result400 = ProblemDetails.fromJS(resultData400);
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过Jtag下载比特流文件
|
||||||
|
* @param address (optional) 设备地址
|
||||||
|
* @param port (optional) 设备端口
|
||||||
|
*/
|
||||||
|
downloadBitstream(address: string | undefined, port: number | undefined): Promise<void> {
|
||||||
|
let url_ = this.baseUrl + "/api/Jtag/DownloadBitstream?";
|
||||||
|
if (address === null)
|
||||||
|
throw new Error("The parameter 'address' cannot be null.");
|
||||||
|
else if (address !== undefined)
|
||||||
|
url_ += "address=" + encodeURIComponent("" + address) + "&";
|
||||||
|
if (port === null)
|
||||||
|
throw new Error("The parameter 'port' cannot be null.");
|
||||||
|
else if (port !== undefined)
|
||||||
|
url_ += "port=" + encodeURIComponent("" + port) + "&";
|
||||||
|
url_ = url_.replace(/[?&]$/, "");
|
||||||
|
|
||||||
|
let options_: RequestInit = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.http.fetch(url_, options_).then((_response: Response) => {
|
||||||
|
return this.processDownloadBitstream(_response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected processDownloadBitstream(response: Response): Promise<void> {
|
||||||
|
const status = response.status;
|
||||||
|
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
|
||||||
|
if (status === 200) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
} else if (status === 400) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
let result400: any = null;
|
||||||
|
let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
|
||||||
|
result400 = ProblemDetails.fromJS(resultData400);
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers, result400);
|
||||||
|
});
|
||||||
|
} else if (status === 500) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("A server side error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
} else if (status !== 200 && status !== 204) {
|
||||||
|
return response.text().then((_responseText) => {
|
||||||
|
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve<void>(null as any);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Package options which to send address to read or write */
|
||||||
|
export class SendAddrPackOptions implements ISendAddrPackOptions {
|
||||||
|
/** 突发类型 */
|
||||||
|
burstType?: BurstType;
|
||||||
|
/** 任务ID */
|
||||||
|
commandID?: number;
|
||||||
|
/** 标识写入还是读取 */
|
||||||
|
isWrite?: boolean;
|
||||||
|
/** 突发长度:0是32bits,255是32bits x 256 */
|
||||||
|
burstLength?: number;
|
||||||
|
/** 目标地址 */
|
||||||
|
address?: number;
|
||||||
|
|
||||||
|
constructor(data?: ISendAddrPackOptions) {
|
||||||
|
if (data) {
|
||||||
|
for (var property in data) {
|
||||||
|
if (data.hasOwnProperty(property))
|
||||||
|
(<any>this)[property] = (<any>data)[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_data?: any) {
|
||||||
|
if (_data) {
|
||||||
|
this.burstType = _data["burstType"];
|
||||||
|
this.commandID = _data["commandID"];
|
||||||
|
this.isWrite = _data["isWrite"];
|
||||||
|
this.burstLength = _data["burstLength"];
|
||||||
|
this.address = _data["address"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJS(data: any): SendAddrPackOptions {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
let result = new SendAddrPackOptions();
|
||||||
|
result.init(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(data?: any) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
data["burstType"] = this.burstType;
|
||||||
|
data["commandID"] = this.commandID;
|
||||||
|
data["isWrite"] = this.isWrite;
|
||||||
|
data["burstLength"] = this.burstLength;
|
||||||
|
data["address"] = this.address;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Package options which to send address to read or write */
|
||||||
|
export interface ISendAddrPackOptions {
|
||||||
|
/** 突发类型 */
|
||||||
|
burstType?: BurstType;
|
||||||
|
/** 任务ID */
|
||||||
|
commandID?: number;
|
||||||
|
/** 标识写入还是读取 */
|
||||||
|
isWrite?: boolean;
|
||||||
|
/** 突发长度:0是32bits,255是32bits x 256 */
|
||||||
|
burstLength?: number;
|
||||||
|
/** 目标地址 */
|
||||||
|
address?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Package Burst Type */
|
||||||
|
export enum BurstType {
|
||||||
|
ExtendBurst = 0,
|
||||||
|
FixedBurst = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** UDP接受数据包格式 */
|
||||||
|
export class UDPData implements IUDPData {
|
||||||
|
/** 接受到的时间 */
|
||||||
|
dateTime?: Date;
|
||||||
|
/** 发送来源的IP地址 */
|
||||||
|
address?: string;
|
||||||
|
/** 发送来源的端口号 */
|
||||||
|
port?: number;
|
||||||
|
/** 接受到的数据 */
|
||||||
|
data?: string;
|
||||||
|
/** 是否被读取过 */
|
||||||
|
hasRead?: boolean;
|
||||||
|
|
||||||
|
constructor(data?: IUDPData) {
|
||||||
|
if (data) {
|
||||||
|
for (var property in data) {
|
||||||
|
if (data.hasOwnProperty(property))
|
||||||
|
(<any>this)[property] = (<any>data)[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_data?: any) {
|
||||||
|
if (_data) {
|
||||||
|
this.dateTime = _data["dateTime"] ? new Date(_data["dateTime"].toString()) : <any>undefined;
|
||||||
|
this.address = _data["address"];
|
||||||
|
this.port = _data["port"];
|
||||||
|
this.data = _data["data"];
|
||||||
|
this.hasRead = _data["hasRead"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJS(data: any): UDPData {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
let result = new UDPData();
|
||||||
|
result.init(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(data?: any) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
data["dateTime"] = this.dateTime ? this.dateTime.toISOString() : <any>undefined;
|
||||||
|
data["address"] = this.address;
|
||||||
|
data["port"] = this.port;
|
||||||
|
data["data"] = this.data;
|
||||||
|
data["hasRead"] = this.hasRead;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** UDP接受数据包格式 */
|
||||||
|
export interface IUDPData {
|
||||||
|
/** 接受到的时间 */
|
||||||
|
dateTime?: Date;
|
||||||
|
/** 发送来源的IP地址 */
|
||||||
|
address?: string;
|
||||||
|
/** 发送来源的端口号 */
|
||||||
|
port?: number;
|
||||||
|
/** 接受到的数据 */
|
||||||
|
data?: string;
|
||||||
|
/** 是否被读取过 */
|
||||||
|
hasRead?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ProblemDetails implements IProblemDetails {
|
||||||
|
type?: string | undefined;
|
||||||
|
title?: string | undefined;
|
||||||
|
status?: number | undefined;
|
||||||
|
detail?: string | undefined;
|
||||||
|
instance?: string | undefined;
|
||||||
|
extensions?: { [key: string]: any; };
|
||||||
|
|
||||||
|
[key: string]: any;
|
||||||
|
|
||||||
|
constructor(data?: IProblemDetails) {
|
||||||
|
if (data) {
|
||||||
|
for (var property in data) {
|
||||||
|
if (data.hasOwnProperty(property))
|
||||||
|
(<any>this)[property] = (<any>data)[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init(_data?: any) {
|
||||||
|
if (_data) {
|
||||||
|
for (var property in _data) {
|
||||||
|
if (_data.hasOwnProperty(property))
|
||||||
|
this[property] = _data[property];
|
||||||
|
}
|
||||||
|
this.type = _data["type"];
|
||||||
|
this.title = _data["title"];
|
||||||
|
this.status = _data["status"];
|
||||||
|
this.detail = _data["detail"];
|
||||||
|
this.instance = _data["instance"];
|
||||||
|
if (_data["extensions"]) {
|
||||||
|
this.extensions = {} as any;
|
||||||
|
for (let key in _data["extensions"]) {
|
||||||
|
if (_data["extensions"].hasOwnProperty(key))
|
||||||
|
(<any>this.extensions)![key] = _data["extensions"][key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromJS(data: any): ProblemDetails {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
let result = new ProblemDetails();
|
||||||
|
result.init(data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON(data?: any) {
|
||||||
|
data = typeof data === 'object' ? data : {};
|
||||||
|
for (var property in this) {
|
||||||
|
if (this.hasOwnProperty(property))
|
||||||
|
data[property] = this[property];
|
||||||
|
}
|
||||||
|
data["type"] = this.type;
|
||||||
|
data["title"] = this.title;
|
||||||
|
data["status"] = this.status;
|
||||||
|
data["detail"] = this.detail;
|
||||||
|
data["instance"] = this.instance;
|
||||||
|
if (this.extensions) {
|
||||||
|
data["extensions"] = {};
|
||||||
|
for (let key in this.extensions) {
|
||||||
|
if (this.extensions.hasOwnProperty(key))
|
||||||
|
(<any>data["extensions"])[key] = (<any>this.extensions)[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IProblemDetails {
|
||||||
|
type?: string | undefined;
|
||||||
|
title?: string | undefined;
|
||||||
|
status?: number | undefined;
|
||||||
|
detail?: string | undefined;
|
||||||
|
instance?: string | undefined;
|
||||||
|
extensions?: { [key: string]: any; };
|
||||||
|
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileParameter {
|
||||||
|
data: any;
|
||||||
|
fileName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ApiException extends Error {
|
||||||
|
message: string;
|
||||||
|
status: number;
|
||||||
|
response: string;
|
||||||
|
headers: { [key: string]: any; };
|
||||||
|
result: any;
|
||||||
|
|
||||||
|
constructor(message: string, status: number, response: string, headers: { [key: string]: any; }, result: any) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.message = message;
|
||||||
|
this.status = status;
|
||||||
|
this.response = response;
|
||||||
|
this.headers = headers;
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected isApiException = true;
|
||||||
|
|
||||||
|
static isApiException(obj: any): obj is ApiException {
|
||||||
|
return obj.isApiException === true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function throwException(message: string, status: number, response: string, headers: { [key: string]: any; }, result?: any): any {
|
||||||
|
if (result !== null && result !== undefined)
|
||||||
|
throw result;
|
||||||
|
else
|
||||||
|
throw new ApiException(message, status, response, headers, null);
|
||||||
|
}
|
Loading…
Reference in New Issue