add nlog for server

This commit is contained in:
SikongJueluo 2025-04-09 19:42:29 +08:00
parent 5c0f5b2127
commit 143d6c634b
No known key found for this signature in database
11 changed files with 358 additions and 77 deletions

12
.justfile Normal file
View File

@ -0,0 +1,12 @@
@_show-dir:
echo "Current Working Directory:"
pwd
echo
[working-directory: "server"]
publish: _show-dir
dotnet publish --self-contained false -t:PublishAllRids
[working-directory: "server"]
run-server: _show-dir
dotnet run

View File

@ -7,7 +7,10 @@
let let
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f { forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs {
inherit system;
config.permittedInsecurePackages = ["dotnet-sdk-6.0.428"];
};
}); });
in in
{ {
@ -26,6 +29,7 @@
dotnetCorePackages.sdk_8_0 dotnetCorePackages.sdk_8_0
]) ])
nuget nuget
# msbuild
omnisharp-roslyn omnisharp-roslyn
csharpier csharpier

View File

@ -1,10 +1,29 @@
using System.Reflection; using System.Reflection;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using NLog;
using NLog.Web;
var builder = WebApplication.CreateBuilder(args); // Early init of NLog to allow startup and exception logging, before host is built
builder.Services.AddEndpointsApiExplorer(); var logger = NLog.LogManager.Setup()
builder.Services.AddSwaggerGen(options => .LoadConfigurationFromAppSettings()
.GetCurrentClassLogger();
logger.Debug("Init Main...");
try
{ {
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
// NLog: Setup NLog for Dependency injection
builder.Logging.ClearProviders();
builder.Host.UseNLog();
builder.Services.AddEndpointsApiExplorer();
// Add Swagger
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo options.SwaggerDoc("v1", new OpenApiInfo
{ {
Title = "FPGA Web Lab API", Title = "FPGA Web Lab API",
@ -21,31 +40,58 @@ builder.Services.AddSwaggerGen(options =>
.Select(assembly => Path.Combine(AppContext.BaseDirectory, $"{assembly.Name}.xml")) .Select(assembly => Path.Combine(AppContext.BaseDirectory, $"{assembly.Name}.xml"))
.Where(path => File.Exists(path)); .Where(path => File.Exists(path));
foreach (var xmlDocPath in referencedProjectsXmlDocPaths) options.IncludeXmlComments(xmlDocPath); foreach (var xmlDocPath in referencedProjectsXmlDocPaths) options.IncludeXmlComments(xmlDocPath);
}); });
var app = builder.Build(); var app = builder.Build();
if (app.Environment.IsDevelopment()) // Configure the HTTP request pipeline.
{ app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
// if (app.Environment.IsDevelopment())
// {
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(c => app.UseSwaggerUI(c =>
{ {
c.SwaggerEndpoint("/swagger/v1/swagger.json", "FPAG WebLab API V1"); c.SwaggerEndpoint("/swagger/v1/swagger.json", "FPAG WebLab API V1");
}); });
// }
// Setup Program
MsgBus.Init();
// Router
app.MapGet("/", () => Results.Redirect("/swagger"));
app.MapPut("/api/SendString", Router.API.SendString);
app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage);
app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage);
app.MapPut("/api/jtag/RunCommand", Router.API.Jtag.RunCommand);
app.MapPut("/api/jtag/GetIDCode", Router.API.Jtag.GetDeviceIDCode);
app.Run("http://localhost:5000");
}
catch (Exception exception)
{
// NLog: catch setup errors
logger.Error(exception, "Stopped program because of exception");
throw;
}
finally
{
// Close UDP Server
logger.Info("Program is Closing now...");
MsgBus.Exit();
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
NLog.LogManager.Shutdown();
} }
// Setup Program
MsgBus.Init();
// Router
app.MapGet("/", () => "Hello World!");
app.MapPut("/api/SendString", Router.API.SendString);
app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage);
app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage);
app.MapPut("/api/jtag/RunCommand", Router.API.Jtag.RunCommand);
app.MapPut("/api/jtag/GetIDCode", Router.API.Jtag.GetDeviceIDCode);
app.Run("http://localhost:5000");
// Close UDP Server
Console.WriteLine("Program is Closing now...");
MsgBus.Exit();

View File

@ -0,0 +1,28 @@
<Project DefaultTargets="Build">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<!-- Enable roll-forward to latest patch. This allows one restore operation
to apply to all of the self-contained publish operations. -->
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
</PropertyGroup>
<Target Name="PublishAllRids">
<ItemGroup>
<!-- Transform RuntimeIdentifiers property to item -->
<RuntimeIdentifierForPublish Include="$(RuntimeIdentifiers)" />
<!-- Transform RuntimeIdentifierForPublish items to project items to pass to MSBuild task -->
<ProjectToPublish Include="@(RuntimeIdentifierForPublish->'$(MSBuildProjectFullPath)')">
<AdditionalProperties>RuntimeIdentifier=%(RuntimeIdentifierForPublish.Identity)</AdditionalProperties>
</ProjectToPublish>
</ItemGroup>
<MSBuild Projects="@(ProjectToPublish)"
Targets="Publish"
BuildInParallel="true"
/>
</Target>
</Project>

View File

@ -2,8 +2,60 @@
"Logging": { "Logging": {
"LogLevel": { "LogLevel": {
"Default": "Information", "Default": "Information",
"Microsoft.AspNetCore": "Warning" "Microsoft": "Warning",
"Microsoft.AspNetCore": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"NLog": {
"RemoveLoggerFactoryFilter": true
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"NLog": {
"extensions": [
{
"assembly": "NLog.Web.AspNetCore"
}
],
"throwConfigExceptions": true,
"targets": {
"async": true,
"AllFile": {
"type": "File",
"fileName": "./log/all-${shortdate}.log"
},
"WebAllFile": {
"type": "File",
"fileName": "./log/web-all-${shortdate}.log"
},
"Console": {
"type": "ColoredConsole"
}
},
"rules": [
{
"logger": "*",
"finalMinLevel": "Trace",
"writeTo": "AllFile"
},
{
"logger": "*",
"finalMinLevel": "Trace",
"writeTo": "WebAllFile"
},
{
"logger": "System.*",
"finalMinLevel": "Warn"
},
{
"logger": "Microsoft.*",
"finalMinLevel": "Warn"
},
{
"logger": "Microsoft.Hosting.Lifetime*",
"finalMinLevel": "Info",
"writeTo": "Console"
}
]
}
} }

View File

@ -1,10 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="PublishAllRids.targets" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<RuntimeIdentifiers>win-x64;linux-x64;</RuntimeIdentifiers>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -13,6 +16,7 @@
<PackageReference Include="Microsoft.OpenApi" Version="1.6.23" /> <PackageReference Include="Microsoft.OpenApi" Version="1.6.23" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.4.0" /> <PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
</ItemGroup> </ItemGroup>

View File

@ -236,11 +236,12 @@ class Jtag
var opts = new SendAddrPackOptions(); var opts = new SendAddrPackOptions();
opts.burstType = BurstType.FixedBurst; opts.burstType = BurstType.FixedBurst;
opts.burstLength = 4; opts.burstLength = 0;
opts.commandID = 0; opts.commandID = 0;
opts.address = devAddr; opts.address = devAddr;
// Read Jtag State Register // Read Jtag State Register
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) throw new Exception("Send Address Package Failed!");
@ -276,7 +277,7 @@ class Jtag
var opts = new SendAddrPackOptions(); var opts = new SendAddrPackOptions();
opts.burstType = BurstType.FixedBurst; opts.burstType = BurstType.FixedBurst;
opts.burstLength = 4; opts.burstLength = 0;
opts.commandID = 0; opts.commandID = 0;
opts.address = devAddr; opts.address = devAddr;
@ -289,6 +290,7 @@ class Jtag
if (!ret) throw new Exception("Send Data Package Failed!"); if (!ret) throw new Exception("Send Data Package Failed!");
// Read Jtag State Register // Read Jtag State Register
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) throw new Exception("Send 2rd Address Package Failed!");

View File

@ -1,19 +1,36 @@
/// <summary>
/// 多线程通信总线
/// </summary>
public static class MsgBus public static class MsgBus
{ {
private static readonly UDPServer udpServer = new UDPServer(33000); private static readonly UDPServer udpServer = new UDPServer(1234);
/// <summary>
/// 获取UDP服务器
/// </summary>
public static UDPServer UDPServer { get { return udpServer; } } public static UDPServer UDPServer { get { return udpServer; } }
private static bool isRunning = false; private static bool isRunning = false;
/// <summary>
/// 获取通信总线运行状态
/// </summary>
public static bool IsRunning { get { return isRunning; } } public static bool IsRunning { get { return isRunning; } }
/// <summary>
/// 通信总线初始化
/// </summary>
/// <returns>无</returns>
public static void Init() public static void Init()
{ {
udpServer.Start(); udpServer.Start();
isRunning = true; isRunning = true;
} }
/// <summary>
/// 关闭通信总线
/// </summary>
/// <returns>无</returns>
public static void Exit() public static void Exit()
{ {
udpServer.Stop(); udpServer.Stop();

View File

@ -16,10 +16,10 @@ namespace Router
class API class API
{ {
/// <summary> /// <summary>
/// Send some String /// 发送字符串
/// </summary> /// </summary>
/// <param name="address">IP V4/V6 address</param> /// <param name="address">IPV4 或者 IPV6 地址</param>
/// <param name="port">Device UDP port</param> /// <param name="port">设备端口号</param>
/// <param name="text">Text for send</param> /// <param name="text">Text for send</param>
/// <returns>Json: true or false</returns> /// <returns>Json: true or false</returns>
public static async ValueTask<IResult> SendString(string address, int port, string text) public static async ValueTask<IResult> SendString(string address, int port, string text)

View File

@ -4,11 +4,24 @@ using System.Text;
using DotNext; using DotNext;
using DotNext.Threading; using DotNext.Threading;
/// <summary> UDP接受数据包格式 </summary>
public struct UDPData public struct UDPData
{ {
/// <summary>
/// 接受到的时间
/// </summary>
public DateTime datetime; public DateTime datetime;
/// <summary>
/// 发送来源的IP地址
/// </summary>
public string addr; public string addr;
/// <summary>
/// 发送来源的端口号
/// </summary>
public int port; public int port;
/// <summary>
/// 接受到的数据
/// </summary>
public byte[] data; public byte[] data;
} }
@ -51,12 +64,19 @@ public class UDPServer
/// Find UDP Receive Data According to ip address /// Find UDP Receive Data According to ip address
/// </summary> /// </summary>
/// <param name="ipAddr"> IP Address</param> /// <param name="ipAddr"> IP Address</param>
/// <param name="rwTimeout"> Read and Write Wait for Milliseconds </param> /// <param name="timeout"> Read and Write Wait for Milliseconds </param>
/// <returns>UDP Data</returns> /// <returns>UDP Data</returns>
public Optional<UDPData> FindData(string ipAddr, int rwTimeout = 1000) public Optional<UDPData> FindData(string ipAddr, int timeout = 1000)
{ {
UDPData? data = null; UDPData? data = null;
using (udpDataLock.AcquireWriteLock(TimeSpan.FromMilliseconds(rwTimeout)))
var startTime = DateTime.Now;
var isTimeout = false;
var timeleft = TimeSpan.FromMilliseconds(timeout);
while (!isTimeout)
{
using (udpDataLock.AcquireWriteLock(timeleft))
{ {
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0) if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
{ {
@ -65,6 +85,10 @@ public class UDPServer
} }
} }
timeleft = DateTime.Now.Subtract(startTime);
isTimeout = timeleft >= TimeSpan.FromMilliseconds(timeout);
}
if (data == null) if (data == null)
{ {
return Optional.None<UDPData>(); return Optional.None<UDPData>();
@ -76,15 +100,26 @@ public class UDPServer
} }
/// <summary> /// <summary>
/// Find UDP Receive Data Async /// 异步寻找目标发送的内容
/// </summary> /// </summary>
/// <param name="ipAddr">[TODO:parameter]</param> /// <param name="ipAddr"> 目标IP地址 </param>
/// <param name="timeout">[TODO:parameter]</param> /// <param name="timeout">超时时间</param>
/// <returns>[TODO:return]</returns> /// <returns>
/// 异步Optional 数据包:
/// Optional 为空时,表明找不到数据;
/// Optional 存在时,为最先收到的数据
/// </returns>
public async ValueTask<Optional<UDPData>> FindDataAsync(string ipAddr, int timeout = 1000) public async ValueTask<Optional<UDPData>> FindDataAsync(string ipAddr, int timeout = 1000)
{ {
UDPData? data = null; UDPData? data = null;
using (await udpDataLock.AcquireWriteLockAsync(TimeSpan.FromMilliseconds(1000)))
var startTime = DateTime.Now;
var isTimeout = false;
var timeleft = TimeSpan.FromMilliseconds(timeout);
while (!isTimeout)
{
using (await udpDataLock.AcquireWriteLockAsync(timeleft))
{ {
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0) if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
{ {
@ -93,6 +128,10 @@ public class UDPServer
} }
} }
timeleft = DateTime.Now.Subtract(startTime);
isTimeout = timeleft >= TimeSpan.FromMilliseconds(timeout);
}
if (data == null) if (data == null)
{ {
return Optional.None<UDPData>(); return Optional.None<UDPData>();
@ -152,8 +191,22 @@ public class UDPServer
recvData = resData.Error.ToString(); recvData = resData.Error.ToString();
} }
else if (sign == (byte)WebProtocol.PackSign.SendData) { } else if (sign == (byte)WebProtocol.PackSign.SendData) { }
else if (sign == (byte)WebProtocol.PackSign.RecvData) { } else if (sign == (byte)WebProtocol.PackSign.RecvData)
else if (sign == (byte)WebProtocol.PackSign.RecvResp) { } {
var resData = WebProtocol.RecvDataPackage.FromBytes(bytes);
if (resData.IsSuccessful)
recvData = resData.Value.Options.ToString();
else
recvData = resData.Error.ToString();
}
else if (sign == (byte)WebProtocol.PackSign.RecvResp)
{
var resData = WebProtocol.RecvRespPackage.FromBytes(bytes);
if (resData.IsSuccessful)
recvData = resData.Value.Options.ToString();
else
recvData = resData.Error.ToString();
}
else else
{ {
recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length); recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length);

View File

@ -42,8 +42,10 @@ namespace WebProtocol
public BurstType burstType; public BurstType burstType;
/// <example>1</example> /// <example>1</example>
public byte commandID; public byte commandID;
/// <summary> 标识写入还是读取 </summary>
/// <example> true </example> /// <example> true </example>
public bool isWrite; public bool isWrite;
/// <summary> 突发长度0是32bits255是32bits x 256 </summary>
/// <example> 255 </example> /// <example> 255 </example>
public byte burstLength; public byte burstLength;
/// <example> 0x10_00_00_00 </example> /// <example> 0x10_00_00_00 </example>
@ -62,6 +64,19 @@ namespace WebProtocol
/// <summary> Package Options which to receive from boards </summary> /// <summary> Package Options which to receive from boards </summary>
public struct RecvPackOptions public struct RecvPackOptions
{ {
/// <summary> 数据包类型 </summary>
public enum PackType
{
/// <summary> 读响应包 </summary>
ReadResp,
/// <summary> 写响应包 </summary>
WriteResp
};
/// <summary>
/// 数据包类型
/// </summary>
public PackType type;
/// <summary> /// <summary>
/// Task ID /// Task ID
/// </summary> /// </summary>
@ -85,7 +100,7 @@ namespace WebProtocol
} }
} }
/// <summary> Package which send address to write </summary> /// <summary> Server->FPGA 地址包 </summary>
public struct SendAddrPackage public struct SendAddrPackage
{ {
readonly byte sign = (byte)PackSign.SendAddr; readonly byte sign = (byte)PackSign.SendAddr;
@ -94,22 +109,36 @@ namespace WebProtocol
readonly byte _reserved = 0; readonly byte _reserved = 0;
readonly UInt32 address; readonly UInt32 address;
/// <summary>
/// 使用地址包选项构造地址包
/// </summary>
/// <param name="opts"> 地址包选项 </param>
public SendAddrPackage(SendAddrPackOptions opts) public SendAddrPackage(SendAddrPackOptions opts)
{ {
byte byteBurstType = Convert.ToByte((byte)opts.burstType << 5); byte byteBurstType = Convert.ToByte((byte)opts.burstType << 6);
byte byteCommandID = Convert.ToByte((opts.commandID & 0x03) << 3); byte byteCommandID = Convert.ToByte((opts.commandID & 0x03) << 4);
byte byteIsWrite = (opts.isWrite ? (byte)0x01 : (byte)0x00); byte byteIsWrite = (opts.isWrite ? (byte)0x01 : (byte)0x00);
this.commandType = Convert.ToByte(byteBurstType | byteCommandID | byteIsWrite); this.commandType = Convert.ToByte(byteBurstType | byteCommandID | byteIsWrite);
this.burstLength = opts.burstLength; this.burstLength = opts.burstLength;
this.address = opts.address; this.address = opts.address;
} }
public SendAddrPackage(BurstType burstType, byte commandID, bool isWrite) /// <summary>
/// 使用完整参数构造地址包
/// </summary>
/// <param name="burstType"> 突发类型 </param>
/// <param name="commandID"> 任务ID </param>
/// <param name="isWrite"> 是否是写数据 </param>
/// <param name="burstLength"> 突发长度 </param>
/// <param name="address"> 设备地址 </param>
public SendAddrPackage(BurstType burstType, byte commandID, bool isWrite, byte burstLength, UInt32 address)
{ {
byte byteBurstType = Convert.ToByte((byte)burstType << 5); byte byteBurstType = Convert.ToByte((byte)burstType << 6);
byte byteCommandID = Convert.ToByte((commandID & 0x03) << 3); byte byteCommandID = Convert.ToByte((commandID & 0x03) << 4);
byte byteIsWrite = (isWrite ? (byte)0x01 : (byte)0x00); byte byteIsWrite = (isWrite ? (byte)0x01 : (byte)0x00);
this.commandType = Convert.ToByte(byteBurstType | byteCommandID | byteIsWrite); this.commandType = Convert.ToByte(byteBurstType | byteCommandID | byteIsWrite);
this.burstLength = burstLength;
this.address = address;
} }
public SendAddrPackage(byte commandType, byte burstLength, UInt32 address) public SendAddrPackage(byte commandType, byte burstLength, UInt32 address)
@ -119,6 +148,10 @@ namespace WebProtocol
this.address = address; this.address = address;
} }
/// <summary>
/// 将地址包转化为字节数组
/// </summary>
/// <returns> 字节数组 </returns>
public byte[] ToBytes() public byte[] ToBytes()
{ {
var arr = new byte[8]; var arr = new byte[8];
@ -133,11 +166,15 @@ namespace WebProtocol
return arr; return arr;
} }
/// <summary>
/// 讲地址包转化为Json格式的地址包选项
/// </summary>
/// <returns> 字符串 </returns>
public override string ToString() public override string ToString()
{ {
SendAddrPackOptions opts; SendAddrPackOptions opts;
opts.burstType = (BurstType)(commandType >> 5); opts.burstType = (BurstType)(commandType >> 6);
opts.commandID = Convert.ToByte((commandType >> 3) & 0b0011); opts.commandID = Convert.ToByte((commandType >> 4) & 0b0011);
opts.isWrite = Convert.ToBoolean(commandType & 0x01); opts.isWrite = Convert.ToBoolean(commandType & 0x01);
opts.burstLength = burstLength; opts.burstLength = burstLength;
opts.address = address; opts.address = address;
@ -194,6 +231,7 @@ namespace WebProtocol
} }
/// <summary> FPGA->Server 读数据包 </summary>
public struct RecvDataPackage public struct RecvDataPackage
{ {
readonly byte sign = (byte)PackSign.RecvData; readonly byte sign = (byte)PackSign.RecvData;
@ -202,6 +240,13 @@ namespace WebProtocol
readonly byte _reserved = 0; readonly byte _reserved = 0;
readonly byte[] bodyData; readonly byte[] bodyData;
/// <summary>
/// FPGA->Server 读数据包
/// 构造函数
/// </summary>
/// <param name="commandID"> 任务ID号 </param>
/// <param name="resp"> 读数据包响应 </param>
/// <param name="bodyData"> 数据 </param>
public RecvDataPackage(byte commandID, byte resp, byte[] bodyData) public RecvDataPackage(byte commandID, byte resp, byte[] bodyData)
{ {
this.commandID = commandID; this.commandID = commandID;
@ -209,13 +254,17 @@ namespace WebProtocol
this.bodyData = bodyData; this.bodyData = bodyData;
} }
/// <summary>
/// 获取读数据包选项
/// </summary>
public RecvPackOptions Options public RecvPackOptions Options
{ {
get get
{ {
RecvPackOptions opts; RecvPackOptions opts;
opts.type = RecvPackOptions.PackType.ReadResp;
opts.commandID = commandID; opts.commandID = commandID;
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false); opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? false : true);
opts.data = bodyData; opts.data = bodyData;
return opts; return opts;
@ -246,14 +295,28 @@ namespace WebProtocol
this.resp = resp; this.resp = resp;
} }
public RecvPackOptions Options() public RecvPackOptions Options
{
get
{ {
RecvPackOptions opts; RecvPackOptions opts;
opts.type = RecvPackOptions.PackType.WriteResp;
opts.commandID = commandID; opts.commandID = commandID;
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false); opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? false : true);
opts.data = null; opts.data = null;
return opts; return opts;
} }
} }
public static Result<RecvRespPackage> FromBytes(byte[] bytes)
{
if (bytes[0] != (byte)PackSign.RecvResp)
throw new ArgumentException(
"The sign of bytes is not RecvData Package!",
nameof(bytes)
);
return new RecvRespPackage(bytes[1], bytes[2]);
}
}
} }