From 5bb011e6855fea4232c55260d2dcea9f8d4a2bc9 Mon Sep 17 00:00:00 2001 From: SikongJueluo Date: Tue, 20 May 2025 11:14:00 +0800 Subject: [PATCH] feag: backend add matrix key peripheral with its web api --- .justfile | 3 + server/src/Common.cs | 16 + server/src/Controllers.cs | 891 --------- .../src/Controllers/BsdlParserController.cs | 30 + server/src/Controllers/DDSController.cs | 108 ++ server/src/Controllers/DataController.cs | 69 + server/src/Controllers/JtagController.cs | 278 +++ server/src/Controllers/MatrixKeyController.cs | 101 ++ .../src/Controllers/RemoteUpdateController.cs | 292 +++ server/src/Controllers/UDPController.cs | 133 ++ server/src/H264Encoder.cs | 0 server/src/H264MediaSource.cs | 0 server/src/JtagClient.cs | 20 +- server/src/{ => Peripherals}/DDSClient.cs | 2 +- server/src/Peripherals/MatrixKeyClient.cs | 89 + server/src/VideoStreamService.cs | 0 src/APIClient.ts | 1595 +++++++++-------- 17 files changed, 2004 insertions(+), 1623 deletions(-) delete mode 100644 server/src/Controllers.cs create mode 100644 server/src/Controllers/BsdlParserController.cs create mode 100644 server/src/Controllers/DDSController.cs create mode 100644 server/src/Controllers/DataController.cs create mode 100644 server/src/Controllers/JtagController.cs create mode 100644 server/src/Controllers/MatrixKeyController.cs create mode 100644 server/src/Controllers/RemoteUpdateController.cs create mode 100644 server/src/Controllers/UDPController.cs delete mode 100644 server/src/H264Encoder.cs delete mode 100644 server/src/H264MediaSource.cs rename server/src/{ => Peripherals}/DDSClient.cs (99%) create mode 100644 server/src/Peripherals/MatrixKeyClient.cs delete mode 100644 server/src/VideoStreamService.cs diff --git a/.justfile b/.justfile index 916d5f5..cda2d8d 100644 --- a/.justfile +++ b/.justfile @@ -24,6 +24,9 @@ update: gen-api: npm run gen-api +gen-api-from-server: + npx nswag openapi2tsclient /input:http://localhost:5000/swagger/v1/swagger.json /output:src/APIClient.ts + # 构建服务器,包含win与linux平台 [working-directory: "server"] build-server self-contained=isSelfContained: _show-dir diff --git a/server/src/Common.cs b/server/src/Common.cs index edf3245..fbc2170 100644 --- a/server/src/Common.cs +++ b/server/src/Common.cs @@ -1,3 +1,4 @@ +using System.Collections; using DotNext; namespace Common @@ -273,6 +274,21 @@ namespace Common return ((srcBits >> location) & ((UInt32)0b1)) == 1; } + /// + /// 将BitArray转化为32bits无符号整型 + /// + /// BitArray比特数组 + /// 32bits无符号整型 + public static Result BitsToNumber(BitArray bits) + { + if (bits.Length > 32) + throw new ArgumentException("Argument length shall be at most 32 bits."); + + var array = new UInt32[1]; + bits.CopyTo(array, 0); + return array[0]; + } + /// /// 字符串转二进制字节数组 diff --git a/server/src/Controllers.cs b/server/src/Controllers.cs deleted file mode 100644 index 522fc16..0000000 --- a/server/src/Controllers.cs +++ /dev/null @@ -1,891 +0,0 @@ -using System.Net; -using Common; -using DotNext; -using Microsoft.AspNetCore.Cors; -using Microsoft.AspNetCore.Mvc; -using Newtonsoft.Json; -using WebProtocol; - -namespace server.Controllers; - -/// -/// UDP API -/// -[ApiController] -[Route("api/[controller]")] -public class UDPController : ControllerBase -{ - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - private const string LOCALHOST = "127.0.0.1"; - - /// - /// 页面 - /// - [HttpGet] - public string Index() - { - return "This is UDP Controller"; - } - - /// - /// 发送字符串 - /// - /// IPV4 或者 IPV6 地址 - /// 设备端口号 - /// 发送的文本 - /// 发送成功 - /// 发送失败 - [HttpPost("SendString")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async ValueTask SendString(string address = LOCALHOST, int port = 1234, string text = "Hello Server!") - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendStringAsync(endPoint, [text]); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - /// - /// 发送二进制数据 - /// - /// IPV4 或者 IPV6 地址 - /// 设备端口号 - /// 16进制文本 - [HttpPost("SendBytes")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async ValueTask SendBytes(string address, int port, string bytes) - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendBytesAsync(endPoint, Number.StringToBytes(bytes)); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - - /// - /// 发送地址包 - /// - /// IP地址 - /// UDP 端口号 - /// 地址包选项 - [HttpPost("SendAddrPackage")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async ValueTask SendAddrPackage( - string address, - int port, - [FromBody] SendAddrPackOptions opts) - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts)); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - /// - /// 发送数据包 - /// - /// IP地址 - /// UDP 端口号 - /// 16进制数据 - [HttpPost("SendDataPackage")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async ValueTask SendDataPackage(string address, int port, string data) - { - var endPoint = new IPEndPoint(IPAddress.Parse(address), port); - var ret = await UDPClientPool.SendDataPackAsync(endPoint, - new WebProtocol.SendDataPackage(Number.StringToBytes(data))); - - if (ret) { return TypedResults.Ok(); } - else { return TypedResults.InternalServerError(); } - } - - /// - /// 获取指定IP地址接受的数据列表 - /// - /// IP地址 - [HttpGet("GetRecvDataArray")] - [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async ValueTask GetRecvDataArray(string address) - { - var ret = await MsgBus.UDPServer.GetDataArrayAsync(address); - - if (ret.HasValue) - { - var dataJson = JsonConvert.SerializeObject(ret.Value); - logger.Debug($"Get Receive Successfully: {dataJson}"); - - return TypedResults.Ok(ret.Value); - } - else - { - logger.Debug("Get Receive Failed"); - return TypedResults.InternalServerError(); - } - } - -} - -/// -/// Jtag API -/// -[ApiController] -[Route("api/[controller]")] -public class JtagController : ControllerBase -{ - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - private const string BITSTREAM_PATH = "bitstream/Jtag"; - - /// - /// 页面 - /// - [HttpGet] - public string Index() - { - return "This is Jtag Controller"; - } - - /// - /// 获取Jtag ID Code - /// - /// 设备地址 - /// 设备端口 - [HttpGet("GetDeviceIDCode")] - [EnableCors("Users")] - [ProducesResponseType(typeof(uint), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask GetDeviceIDCode(string address, int port) - { - var jtagCtrl = new JtagClient.Jtag(address, port); - var ret = await jtagCtrl.ReadIDCode(); - - if (ret.IsSuccessful) - { - logger.Info($"Get device {address} ID code: 0x{ret.Value:X4}"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - } - - /// - /// 获取状态寄存器 - /// - /// 设备地址 - /// 设备端口 - [HttpGet("ReadStatusReg")] - [ProducesResponseType(StatusCodes.Status200OK)] - [ProducesResponseType(StatusCodes.Status500InternalServerError)] - public async ValueTask ReadStatusReg(string address, int port) - { - var jtagCtrl = new JtagClient.Jtag(address, port); - var ret = await jtagCtrl.ReadStatusReg(); - - if (ret.IsSuccessful) - { - var binaryValue = Common.String.Reverse(Convert.ToString(ret.Value, 2).PadLeft(32, '0')); - var decodeValue = new JtagClient.JtagStatusReg(ret.Value); - logger.Info($"Read device {address} Status Register: \n\t 0b{binaryValue} \n\t {decodeValue}"); - return TypedResults.Ok(new - { - original = ret.Value, - binaryValue, - decodeValue, - }); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - } - - /// - /// 上传比特流文件 - /// - /// 设备地址 - /// 比特流文件 - [HttpPost("UploadBitstream")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] - public async ValueTask UploadBitstream(string address, IFormFile file) - { - if (file == null || file.Length == 0) - return TypedResults.BadRequest("未选择文件"); - - // 生成安全的文件名(避免路径遍历攻击) - var fileName = Path.GetRandomFileName(); - var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); - - // 如果存在文件,则删除原文件再上传 - if (Directory.Exists(uploadsFolder)) - { - Directory.Delete(uploadsFolder, true); - } - Directory.CreateDirectory(uploadsFolder); - - var filePath = Path.Combine(uploadsFolder, fileName); - - using (var stream = new FileStream(filePath, FileMode.Create)) - { - await file.CopyToAsync(stream); - } - - logger.Info($"Device {address} Upload Bitstream Successfully"); - return TypedResults.Ok(true); - } - - /// - /// 通过Jtag下载比特流文件 - /// - /// 设备地址 - /// 设备端口 - [HttpPost("DownloadBitstream")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask DownloadBitstream(string address, int port) - { - // 检查文件 - var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); - if (!Directory.Exists(fileDir)) - return TypedResults.BadRequest("Empty bitstream, Please upload it first"); - - try - { - // 读取文件 - var filePath = Directory.GetFiles(fileDir)[0]; - - using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open)) - { - if (fileStream is null || fileStream.Length <= 0) - return TypedResults.BadRequest("Wrong bitstream, Please upload it again"); - - // 定义缓冲区大小: 32KB - byte[] buffer = new byte[32 * 1024]; - byte[] revBuffer = new byte[32 * 1024]; - long totalBytesRead = 0; - - // 使用异步流读取文件 - using (var memoryStream = new MemoryStream()) - { - int bytesRead; - while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0) - { - // 反转 32bits - var retBuffer = Common.Number.ReverseBytes(buffer, 4); - if (!retBuffer.IsSuccessful) - return TypedResults.InternalServerError(retBuffer.Error); - revBuffer = retBuffer.Value; - - for (int i = 0; i < revBuffer.Length; i++) - { - revBuffer[i] = Common.Number.ReverseBits(revBuffer[i]); - } - - await memoryStream.WriteAsync(revBuffer, 0, bytesRead); - totalBytesRead += bytesRead; - } - - // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存) - var fileBytes = memoryStream.ToArray(); - - // 下载比特流 - var jtagCtrl = new JtagClient.Jtag(address, port); - var ret = await jtagCtrl.DownloadBitstream(fileBytes); - - if (ret.IsSuccessful) - { - logger.Info($"Device {address} dowload bitstream successfully"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - } - - } - - } - catch (Exception error) - { - return TypedResults.InternalServerError(error); - } - finally - { - - } - } - - /// - /// [TODO:description] - /// - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:return] - [HttpPost("BoundaryScanAllPorts")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask BoundaryScanAllPorts(string address, int port) - { - var jtagCtrl = new JtagClient.Jtag(address, port); - var ret = await jtagCtrl.BoundaryScan(); - if (!ret.IsSuccessful) - { - if (ret.Error is ArgumentException) - return TypedResults.BadRequest(ret.Error); - else return TypedResults.InternalServerError(ret.Error); - } - - return TypedResults.Ok(ret.Value); - } - - /// - /// [TODO:description] - /// - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:return] - [HttpPost("BoundaryScanLogicalPorts")] - [EnableCors("Users")] - [ProducesResponseType(typeof(Dictionary), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask BoundaryScanLogicalPorts(string address, int port) - { - var jtagCtrl = new JtagClient.Jtag(address, port); - var ret = await jtagCtrl.BoundaryScanLogicalPorts(); - if (!ret.IsSuccessful) - { - if (ret.Error is ArgumentException) - return TypedResults.BadRequest(ret.Error); - else return TypedResults.InternalServerError(ret.Error); - } - - return TypedResults.Ok(ret.Value); - } - - /// - /// [TODO:description] - /// - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:return] - [HttpPost("SetSpeed")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask SetSpeed(string address, int port, UInt32 speed) - { - var jtagCtrl = new JtagClient.Jtag(address, port); - var ret = await jtagCtrl.SetSpeed(speed); - if (!ret.IsSuccessful) - { - if (ret.Error is ArgumentException) - return TypedResults.BadRequest(ret.Error); - else return TypedResults.InternalServerError(ret.Error); - } - - return TypedResults.Ok(ret.Value); - } -} - -/// -/// 远程更新 -/// -[ApiController] -[Route("api/[controller]")] -public class RemoteUpdateController : ControllerBase -{ - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - private const string BITSTREAM_PATH = "bitstream/RemoteUpdate"; - - /// - /// 上传远程更新比特流文件 - /// - /// 设备地址 - /// 黄金比特流文件 - /// 比特流文件1 - /// 比特流文件2 - /// 比特流文件3 - /// 上传结果 - [HttpPost("UploadBitstream")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - public async ValueTask UploadBitstreams( - string address, - IFormFile? goldenBitream, - IFormFile? bitstream1, - IFormFile? bitstream2, - IFormFile? bitstream3) - { - if ((goldenBitream is null || goldenBitream.Length == 0) && - (bitstream1 is null || bitstream1.Length == 0) && - (bitstream2 is null || bitstream2.Length == 0) && - (bitstream3 is null || bitstream3.Length == 0)) - return TypedResults.BadRequest("未选择文件"); - - // 生成安全的文件名(避免路径遍历攻击) - var fileName = Path.GetRandomFileName(); - var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); - - // 如果存在文件,则删除原文件再上传 - if (Directory.Exists(uploadsFolder)) - { - Directory.Delete(uploadsFolder, true); - } - Directory.CreateDirectory(uploadsFolder); - - for (int bitstreamNum = 0; bitstreamNum < 4; bitstreamNum++) - { - IFormFile file; - if (bitstreamNum == 0 && goldenBitream is not null) - file = goldenBitream; - else if (bitstreamNum == 1 && bitstream1 is not null) - file = bitstream1; - else if (bitstreamNum == 2 && bitstream2 is not null) - file = bitstream2; - else if (bitstreamNum == 3 && bitstream3 is not null) - file = bitstream3; - else continue; - - var fileFolder = Path.Combine(uploadsFolder, bitstreamNum.ToString()); - Directory.CreateDirectory(fileFolder); - - var filePath = Path.Combine(fileFolder, fileName); - - using (var stream = new FileStream(filePath, FileMode.Create)) - { - await file.CopyToAsync(stream); - } - } - - logger.Info($"Device {address} Upload Bitstream Successfully"); - return TypedResults.Ok(true); - } - - private async ValueTask> ProcessBitstream(string filePath) - { - using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open)) - { - if (fileStream is null || fileStream.Length <= 0) - return new(new ArgumentException("Wrong bitstream path")); - - // 定义缓冲区大小: 32KB - byte[] buffer = new byte[32 * 1024]; - byte[] revBuffer = new byte[32 * 1024]; - long totalBytesRead = 0; - - // 使用异步流读取文件 - using (var memoryStream = new MemoryStream()) - { - int bytesRead; - while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0) - { - // 反转 32bits - var retBuffer = Common.Number.ReverseBytes(buffer, 4); - if (!retBuffer.IsSuccessful) - return new(retBuffer.Error); - revBuffer = retBuffer.Value; - - await memoryStream.WriteAsync(revBuffer, 0, bytesRead); - totalBytesRead += bytesRead; - } - - // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存) - var restStreamLen = memoryStream.Length % (4 * 1024); - if (restStreamLen != 0) - { - var appendLen = ((int)(4 * 1024 - restStreamLen)); - var bytesAppend = new byte[appendLen]; - Array.Fill(bytesAppend, 0xFF); - await memoryStream.WriteAsync(bytesAppend, 0, appendLen); - } - - return new(memoryStream.ToArray()); - } - } - } - - /// - /// 远程更新单个比特流文件 - /// - /// 设备地址 - /// 设备端口 - /// 比特流位号 - [HttpPost("DownloadBitstream")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask UpdateBitstream(string address, int port, int bitstreamNum) - { - // 检查文件 - var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}/{bitstreamNum}"); - if (!Directory.Exists(fileDir)) - return TypedResults.BadRequest("Empty bitstream, Please upload it first"); - - try - { - // 读取文件 - var filePath = Directory.GetFiles(fileDir)[0]; - - var fileBytes = await ProcessBitstream(filePath); - if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error); - - // 下载比特流 - var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); - var ret = await remoteUpdater.UpdateBitstream(bitstreamNum, fileBytes.Value); - - if (ret.IsSuccessful) - { - logger.Info($"Device {address} Update bitstream successfully"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - - } - catch (Exception error) - { - return TypedResults.InternalServerError(error); - } - } - - - /// - /// 下载多个比特流文件 - /// - /// 设备地址 - /// 设备端口 - /// 比特流编号 - /// 总共上传比特流的数量 - [HttpPost("DownloadMultiBitstreams")] - [EnableCors("Users")] - [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask DownloadMultiBitstreams(string address, int port, int? bitstreamNum) - { - // 检查文件 - var bitstreamsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); - if (!Directory.Exists(bitstreamsFolder)) - return TypedResults.BadRequest("Empty bitstream, Please upload it first"); - - try - { - var bitstreams = new List() { null, null, null, null }; - int cnt = 0; // 上传比特流数量 - for (int i = 0; i < 4; i++) - { - var bitstreamDir = Path.Combine(bitstreamsFolder, i.ToString()); - if (!Directory.Exists(bitstreamDir)) - continue; - cnt++; - - // 读取文件 - var filePath = Directory.GetFiles(bitstreamDir)[0]; - var fileBytes = await ProcessBitstream(filePath); - if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error); - bitstreams[i] = fileBytes.Value; - } - - // 下载比特流 - var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); - { - var ret = await remoteUpdater.UploadBitstreams(bitstreams[0], bitstreams[1], bitstreams[2], bitstreams[3]); - if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error); - if (!ret.Value) return TypedResults.InternalServerError("Upload MultiBitstreams failed"); - } - - if (bitstreamNum is not null) - { - var ret = await remoteUpdater.HotResetBitstream(bitstreamNum ?? 0); - if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error); - if (!ret.Value) return TypedResults.InternalServerError("Hot reset failed"); - } - return TypedResults.Ok(cnt); - } - catch (Exception error) - { - return TypedResults.InternalServerError(error); - } - } - - - /// - /// 热复位比特流文件 - /// - /// 设备地址 - /// 设备端口 - /// 比特流编号 - /// 操作结果 - [HttpPost("HotResetBitstream")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask HotResetBitstream(string address, int port, int bitstreamNum) - { - var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); - var ret = await remoteUpdater.HotResetBitstream(bitstreamNum); - - if (ret.IsSuccessful) - { - logger.Info($"Device {address} Update bitstream successfully"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - } - - /// - /// [TODO:description] - /// - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:return] - [HttpPost("GetFirmwareVersion")] - [EnableCors("Users")] - [ProducesResponseType(typeof(UInt32), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask GetFirmwareVersion(string address, int port) - { - var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); - var ret = await remoteUpdater.GetVersion(); - - if (ret.IsSuccessful) - { - logger.Info($"Device {address} get firmware version successfully"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - } - -} - -/// -/// [TODO:description] -/// -[ApiController] -[Route("api/[controller]")] -public class DDSController : ControllerBase -{ - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - /// - /// [TODO:description] - /// - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:return] - [HttpPost("SetWaveNum")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask SetWaveNum(string address, int port, int channelNum, int waveNum) - { - var dds = new DDSClient.DDS(address, port); - - var ret = await dds.SetWaveNum(channelNum, waveNum); - if (ret.IsSuccessful) - { - logger.Info($"Device {address} set output wave num successfully"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - } - - /// - /// [TODO:description] - /// - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:return] - [HttpPost("SetFreq")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask SetFreq(string address, int port, int channelNum, int waveNum, UInt32 step) - { - var dds = new DDSClient.DDS(address, port); - - var ret = await dds.SetFreq(channelNum, waveNum, step); - if (ret.IsSuccessful) - { - logger.Info($"Device {address} set output freqency successfully"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - } - - /// - /// [TODO:description] - /// - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:parameter] - /// [TODO:return] - [HttpPost("SetPhase")] - [EnableCors("Users")] - [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] - [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] - [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] - public async ValueTask SetPhase(string address, int port, int channelNum, int waveNum, int phase) - { - var dds = new DDSClient.DDS(address, port); - - var ret = await dds.SetPhase(channelNum, waveNum, phase); - if (ret.IsSuccessful) - { - logger.Info($"Device {address} set output phase successfully"); - return TypedResults.Ok(ret.Value); - } - else - { - logger.Error(ret.Error); - return TypedResults.InternalServerError(ret.Error); - } - - } - -} - - -/// -/// [TODO:description] -/// -[ApiController] -[Route("api/[controller]")] -public class BsdlParserController : ControllerBase -{ - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - /// - /// [TODO:description] - /// - /// [TODO:return] - [EnableCors("Development")] - [HttpGet("GetBoundaryLogicalPorts")] - public IResult GetBoundaryLogicalPorts() - { - var parser = new BsdlParser.Parser(); - var ret = parser.GetBoundaryLogicalPorts(); - if (ret.IsNull) return TypedResults.InternalServerError("Get Null"); - return TypedResults.Ok(ret.Value); - } -} - - -/// -/// 数据控制器 -/// -[ApiController] -[Route("api/[controller]")] -public class DataController : ControllerBase -{ - private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); - - /// - /// 创建数据库表 - /// - /// 插入的记录数 - [EnableCors("Development")] - [HttpPost("CreateTable")] - public IResult CreateTables() - { - using var db = new Database.AppDataConnection(); - db.CreateAllTables(); - return TypedResults.Ok(); - } - - /// - /// 删除数据库表 - /// - /// 插入的记录数 - [EnableCors("Development")] - [HttpDelete("DropTables")] - public IResult DropTables() - { - using var db = new Database.AppDataConnection(); - db.DropAllTables(); - return TypedResults.Ok(); - } - - /// - /// 获取所有用户 - /// - /// 用户列表 - [HttpGet("AllUsers")] - public IResult AllUsers() - { - using var db = new Database.AppDataConnection(); - var ret = db.User.ToList(); - return TypedResults.Ok(ret); - } - - /// - /// 注册新用户 - /// - /// 用户名 - /// 操作结果 - [HttpPost("SignUpUser")] - public IResult SignUpUser(string name) - { - if (name.Length > 255) - return TypedResults.BadRequest("Name Couln't over 255 characters"); - - using var db = new Database.AppDataConnection(); - var ret = db.AddUser(name); - return TypedResults.Ok(ret); - } -} - diff --git a/server/src/Controllers/BsdlParserController.cs b/server/src/Controllers/BsdlParserController.cs new file mode 100644 index 0000000..bc166f5 --- /dev/null +++ b/server/src/Controllers/BsdlParserController.cs @@ -0,0 +1,30 @@ +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace server.Controllers; + +/// +/// [TODO:description] +/// +[ApiController] +[Route("api/[controller]")] +public class BsdlParserController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + /// + /// [TODO:description] + /// + /// [TODO:return] + [EnableCors("Development")] + [HttpGet("GetBoundaryLogicalPorts")] + public IResult GetBoundaryLogicalPorts() + { + var parser = new BsdlParser.Parser(); + var ret = parser.GetBoundaryLogicalPorts(); + if (ret.IsNull) return TypedResults.InternalServerError("Get Null"); + return TypedResults.Ok(ret.Value); + } +} + + diff --git a/server/src/Controllers/DDSController.cs b/server/src/Controllers/DDSController.cs new file mode 100644 index 0000000..6e18847 --- /dev/null +++ b/server/src/Controllers/DDSController.cs @@ -0,0 +1,108 @@ +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace server.Controllers; + +/// +/// [TODO:description] +/// +[ApiController] +[Route("api/[controller]")] +public class DDSController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + /// + /// [TODO:description] + /// + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:return] + [HttpPost("SetWaveNum")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask SetWaveNum(string address, int port, int channelNum, int waveNum) + { + var dds = new Peripherals.DDSClient.DDS(address, port); + + var ret = await dds.SetWaveNum(channelNum, waveNum); + if (ret.IsSuccessful) + { + logger.Info($"Device {address} set output wave num successfully"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + /// + /// [TODO:description] + /// + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:return] + [HttpPost("SetFreq")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask SetFreq(string address, int port, int channelNum, int waveNum, UInt32 step) + { + var dds = new Peripherals.DDSClient.DDS(address, port); + + var ret = await dds.SetFreq(channelNum, waveNum, step); + if (ret.IsSuccessful) + { + logger.Info($"Device {address} set output freqency successfully"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + /// + /// [TODO:description] + /// + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:return] + [HttpPost("SetPhase")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask SetPhase(string address, int port, int channelNum, int waveNum, int phase) + { + var dds = new Peripherals.DDSClient.DDS(address, port); + + var ret = await dds.SetPhase(channelNum, waveNum, phase); + if (ret.IsSuccessful) + { + logger.Info($"Device {address} set output phase successfully"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + + } + +} diff --git a/server/src/Controllers/DataController.cs b/server/src/Controllers/DataController.cs new file mode 100644 index 0000000..e656ace --- /dev/null +++ b/server/src/Controllers/DataController.cs @@ -0,0 +1,69 @@ +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace server.Controllers; + +/// +/// 数据控制器 +/// +[ApiController] +[Route("api/[controller]")] +public class DataController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + /// + /// 创建数据库表 + /// + /// 插入的记录数 + [EnableCors("Development")] + [HttpPost("CreateTable")] + public IResult CreateTables() + { + using var db = new Database.AppDataConnection(); + db.CreateAllTables(); + return TypedResults.Ok(); + } + + /// + /// 删除数据库表 + /// + /// 插入的记录数 + [EnableCors("Development")] + [HttpDelete("DropTables")] + public IResult DropTables() + { + using var db = new Database.AppDataConnection(); + db.DropAllTables(); + return TypedResults.Ok(); + } + + /// + /// 获取所有用户 + /// + /// 用户列表 + [HttpGet("AllUsers")] + public IResult AllUsers() + { + using var db = new Database.AppDataConnection(); + var ret = db.User.ToList(); + return TypedResults.Ok(ret); + } + + /// + /// 注册新用户 + /// + /// 用户名 + /// 操作结果 + [HttpPost("SignUpUser")] + public IResult SignUpUser(string name) + { + if (name.Length > 255) + return TypedResults.BadRequest("Name Couln't over 255 characters"); + + using var db = new Database.AppDataConnection(); + var ret = db.AddUser(name); + return TypedResults.Ok(ret); + } +} + diff --git a/server/src/Controllers/JtagController.cs b/server/src/Controllers/JtagController.cs new file mode 100644 index 0000000..a4f0da5 --- /dev/null +++ b/server/src/Controllers/JtagController.cs @@ -0,0 +1,278 @@ +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace server.Controllers; + +/// +/// Jtag API +/// +[ApiController] +[Route("api/[controller]")] +public class JtagController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + private const string BITSTREAM_PATH = "bitstream/Jtag"; + + /// + /// 页面 + /// + [HttpGet] + public string Index() + { + return "This is Jtag Controller"; + } + + /// + /// 获取Jtag ID Code + /// + /// 设备地址 + /// 设备端口 + [HttpGet("GetDeviceIDCode")] + [EnableCors("Users")] + [ProducesResponseType(typeof(uint), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask GetDeviceIDCode(string address, int port) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.ReadIDCode(); + + if (ret.IsSuccessful) + { + logger.Info($"Get device {address} ID code: 0x{ret.Value:X4}"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + /// + /// 获取状态寄存器 + /// + /// 设备地址 + /// 设备端口 + [HttpGet("ReadStatusReg")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask ReadStatusReg(string address, int port) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.ReadStatusReg(); + + if (ret.IsSuccessful) + { + var binaryValue = Common.String.Reverse(Convert.ToString(ret.Value, 2).PadLeft(32, '0')); + var decodeValue = new JtagClient.JtagStatusReg(ret.Value); + logger.Info($"Read device {address} Status Register: \n\t 0b{binaryValue} \n\t {decodeValue}"); + return TypedResults.Ok(new + { + original = ret.Value, + binaryValue, + decodeValue, + }); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + /// + /// 上传比特流文件 + /// + /// 设备地址 + /// 比特流文件 + [HttpPost("UploadBitstream")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] + public async ValueTask UploadBitstream(string address, IFormFile file) + { + if (file == null || file.Length == 0) + return TypedResults.BadRequest("未选择文件"); + + // 生成安全的文件名(避免路径遍历攻击) + var fileName = Path.GetRandomFileName(); + var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); + + // 如果存在文件,则删除原文件再上传 + if (Directory.Exists(uploadsFolder)) + { + Directory.Delete(uploadsFolder, true); + } + Directory.CreateDirectory(uploadsFolder); + + var filePath = Path.Combine(uploadsFolder, fileName); + + using (var stream = new FileStream(filePath, FileMode.Create)) + { + await file.CopyToAsync(stream); + } + + logger.Info($"Device {address} Upload Bitstream Successfully"); + return TypedResults.Ok(true); + } + + /// + /// 通过Jtag下载比特流文件 + /// + /// 设备地址 + /// 设备端口 + [HttpPost("DownloadBitstream")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask DownloadBitstream(string address, int port) + { + // 检查文件 + var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); + if (!Directory.Exists(fileDir)) + return TypedResults.BadRequest("Empty bitstream, Please upload it first"); + + try + { + // 读取文件 + var filePath = Directory.GetFiles(fileDir)[0]; + + using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open)) + { + if (fileStream is null || fileStream.Length <= 0) + return TypedResults.BadRequest("Wrong bitstream, Please upload it again"); + + // 定义缓冲区大小: 32KB + byte[] buffer = new byte[32 * 1024]; + byte[] revBuffer = new byte[32 * 1024]; + long totalBytesRead = 0; + + // 使用异步流读取文件 + using (var memoryStream = new MemoryStream()) + { + int bytesRead; + while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + // 反转 32bits + var retBuffer = Common.Number.ReverseBytes(buffer, 4); + if (!retBuffer.IsSuccessful) + return TypedResults.InternalServerError(retBuffer.Error); + revBuffer = retBuffer.Value; + + for (int i = 0; i < revBuffer.Length; i++) + { + revBuffer[i] = Common.Number.ReverseBits(revBuffer[i]); + } + + await memoryStream.WriteAsync(revBuffer, 0, bytesRead); + totalBytesRead += bytesRead; + } + + // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存) + var fileBytes = memoryStream.ToArray(); + + // 下载比特流 + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.DownloadBitstream(fileBytes); + + if (ret.IsSuccessful) + { + logger.Info($"Device {address} dowload bitstream successfully"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + } + + } + catch (Exception error) + { + return TypedResults.InternalServerError(error); + } + finally + { + + } + } + + /// + /// [TODO:description] + /// + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:return] + [HttpPost("BoundaryScanAllPorts")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(string), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask BoundaryScanAllPorts(string address, int port) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.BoundaryScan(); + if (!ret.IsSuccessful) + { + if (ret.Error is ArgumentException) + return TypedResults.BadRequest(ret.Error); + else return TypedResults.InternalServerError(ret.Error); + } + + return TypedResults.Ok(ret.Value); + } + + /// + /// [TODO:description] + /// + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:return] + [HttpPost("BoundaryScanLogicalPorts")] + [EnableCors("Users")] + [ProducesResponseType(typeof(Dictionary), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask BoundaryScanLogicalPorts(string address, int port) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.BoundaryScanLogicalPorts(); + if (!ret.IsSuccessful) + { + if (ret.Error is ArgumentException) + return TypedResults.BadRequest(ret.Error); + else return TypedResults.InternalServerError(ret.Error); + } + + return TypedResults.Ok(ret.Value); + } + + /// + /// [TODO:description] + /// + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:return] + [HttpPost("SetSpeed")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask SetSpeed(string address, int port, UInt32 speed) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.SetSpeed(speed); + if (!ret.IsSuccessful) + { + if (ret.Error is ArgumentException) + return TypedResults.BadRequest(ret.Error); + else return TypedResults.InternalServerError(ret.Error); + } + + return TypedResults.Ok(ret.Value); + } +} diff --git a/server/src/Controllers/MatrixKeyController.cs b/server/src/Controllers/MatrixKeyController.cs new file mode 100644 index 0000000..40fa7de --- /dev/null +++ b/server/src/Controllers/MatrixKeyController.cs @@ -0,0 +1,101 @@ +using System.Collections; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace server.Controllers; + +/// +/// 矩阵键控制器,用于管理矩阵键的启用、禁用和状态设置 +/// +[ApiController] +[Route("api/[controller]")] +public class MatrixKeyController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + /// + /// 启用矩阵键控制。 + /// + /// 设备的IP地址 + /// 设备的端口号 + /// 返回操作结果的状态码 + [HttpGet("EnabelMatrixKey")] + [EnableCors("Users")] + [ProducesResponseType(typeof(uint), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask EnabelMatrixKey(string address, int port) + { + var matrixKeyCtrl = new Peripherals.MatrixKeyClient.MatrixKey(address, port); + var ret = await matrixKeyCtrl.EnableControl(); + + if (ret.IsSuccessful) + { + logger.Info($"Enable device {address}:{port.ToString()} matrix key finished: {ret.Value}."); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + /// + /// 禁用矩阵键控制。 + /// + /// 设备的IP地址 + /// 设备的端口号 + /// 返回操作结果的状态码 + [HttpGet("DisableMatrixKey")] + [EnableCors("Users")] + [ProducesResponseType(typeof(uint), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask DisableMatrixKey(string address, int port) + { + var matrixKeyCtrl = new Peripherals.MatrixKeyClient.MatrixKey(address, port); + var ret = await matrixKeyCtrl.DisableControl(); + + if (ret.IsSuccessful) + { + logger.Info($"Disable device {address}:{port.ToString()} matrix key finished: {ret.Value}."); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + /// + /// 设置矩阵键的状态。 + /// + /// 设备的IP地址 + /// 设备的端口号 + /// 矩阵键的状态数组,长度应为16 + /// 返回操作结果的状态码 + [HttpGet("SetMatrixKeyStatus")] + [EnableCors("Users")] + [ProducesResponseType(typeof(uint), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask SetMatrixKeyStatus(string address, int port, [FromBody] bool[] keyStates) + { + if (keyStates.Length != 16) + return TypedResults.BadRequest($"The length of key states should be 16 instead of {keyStates.Length}"); + + var matrixKeyCtrl = new Peripherals.MatrixKeyClient.MatrixKey(address, port); + var ret = await matrixKeyCtrl.ControlKey(new BitArray(keyStates)); + + if (ret.IsSuccessful) + { + logger.Info($"Set device {address}:{port.ToString()} matrix key finished: {ret.Value}."); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } +} + diff --git a/server/src/Controllers/RemoteUpdateController.cs b/server/src/Controllers/RemoteUpdateController.cs new file mode 100644 index 0000000..36eb84e --- /dev/null +++ b/server/src/Controllers/RemoteUpdateController.cs @@ -0,0 +1,292 @@ +using DotNext; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace server.Controllers; + +/// +/// 远程更新 +/// +[ApiController] +[Route("api/[controller]")] +public class RemoteUpdateController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + private const string BITSTREAM_PATH = "bitstream/RemoteUpdate"; + + /// + /// 上传远程更新比特流文件 + /// + /// 设备地址 + /// 黄金比特流文件 + /// 比特流文件1 + /// 比特流文件2 + /// 比特流文件3 + /// 上传结果 + [HttpPost("UploadBitstream")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + public async ValueTask UploadBitstreams( + string address, + IFormFile? goldenBitream, + IFormFile? bitstream1, + IFormFile? bitstream2, + IFormFile? bitstream3) + { + if ((goldenBitream is null || goldenBitream.Length == 0) && + (bitstream1 is null || bitstream1.Length == 0) && + (bitstream2 is null || bitstream2.Length == 0) && + (bitstream3 is null || bitstream3.Length == 0)) + return TypedResults.BadRequest("未选择文件"); + + // 生成安全的文件名(避免路径遍历攻击) + var fileName = Path.GetRandomFileName(); + var uploadsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); + + // 如果存在文件,则删除原文件再上传 + if (Directory.Exists(uploadsFolder)) + { + Directory.Delete(uploadsFolder, true); + } + Directory.CreateDirectory(uploadsFolder); + + for (int bitstreamNum = 0; bitstreamNum < 4; bitstreamNum++) + { + IFormFile file; + if (bitstreamNum == 0 && goldenBitream is not null) + file = goldenBitream; + else if (bitstreamNum == 1 && bitstream1 is not null) + file = bitstream1; + else if (bitstreamNum == 2 && bitstream2 is not null) + file = bitstream2; + else if (bitstreamNum == 3 && bitstream3 is not null) + file = bitstream3; + else continue; + + var fileFolder = Path.Combine(uploadsFolder, bitstreamNum.ToString()); + Directory.CreateDirectory(fileFolder); + + var filePath = Path.Combine(fileFolder, fileName); + + using (var stream = new FileStream(filePath, FileMode.Create)) + { + await file.CopyToAsync(stream); + } + } + + logger.Info($"Device {address} Upload Bitstream Successfully"); + return TypedResults.Ok(true); + } + + private async ValueTask> ProcessBitstream(string filePath) + { + using (var fileStream = System.IO.File.Open(filePath, System.IO.FileMode.Open)) + { + if (fileStream is null || fileStream.Length <= 0) + return new(new ArgumentException("Wrong bitstream path")); + + // 定义缓冲区大小: 32KB + byte[] buffer = new byte[32 * 1024]; + byte[] revBuffer = new byte[32 * 1024]; + long totalBytesRead = 0; + + // 使用异步流读取文件 + using (var memoryStream = new MemoryStream()) + { + int bytesRead; + while ((bytesRead = await fileStream.ReadAsync(buffer, 0, buffer.Length)) > 0) + { + // 反转 32bits + var retBuffer = Common.Number.ReverseBytes(buffer, 4); + if (!retBuffer.IsSuccessful) + return new(retBuffer.Error); + revBuffer = retBuffer.Value; + + await memoryStream.WriteAsync(revBuffer, 0, bytesRead); + totalBytesRead += bytesRead; + } + + // 将所有数据转换为字节数组(注意:如果文件非常大,可能不适合完全加载到内存) + var restStreamLen = memoryStream.Length % (4 * 1024); + if (restStreamLen != 0) + { + var appendLen = ((int)(4 * 1024 - restStreamLen)); + var bytesAppend = new byte[appendLen]; + Array.Fill(bytesAppend, 0xFF); + await memoryStream.WriteAsync(bytesAppend, 0, appendLen); + } + + return new(memoryStream.ToArray()); + } + } + } + + /// + /// 远程更新单个比特流文件 + /// + /// 设备地址 + /// 设备端口 + /// 比特流位号 + [HttpPost("DownloadBitstream")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask UpdateBitstream(string address, int port, int bitstreamNum) + { + // 检查文件 + var fileDir = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}/{bitstreamNum}"); + if (!Directory.Exists(fileDir)) + return TypedResults.BadRequest("Empty bitstream, Please upload it first"); + + try + { + // 读取文件 + var filePath = Directory.GetFiles(fileDir)[0]; + + var fileBytes = await ProcessBitstream(filePath); + if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error); + + // 下载比特流 + var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); + var ret = await remoteUpdater.UpdateBitstream(bitstreamNum, fileBytes.Value); + + if (ret.IsSuccessful) + { + logger.Info($"Device {address} Update bitstream successfully"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + + } + catch (Exception error) + { + return TypedResults.InternalServerError(error); + } + } + + + /// + /// 下载多个比特流文件 + /// + /// 设备地址 + /// 设备端口 + /// 比特流编号 + /// 总共上传比特流的数量 + [HttpPost("DownloadMultiBitstreams")] + [EnableCors("Users")] + [ProducesResponseType(typeof(int), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask DownloadMultiBitstreams(string address, int port, int? bitstreamNum) + { + // 检查文件 + var bitstreamsFolder = Path.Combine(Environment.CurrentDirectory, $"{BITSTREAM_PATH}/{address}"); + if (!Directory.Exists(bitstreamsFolder)) + return TypedResults.BadRequest("Empty bitstream, Please upload it first"); + + try + { + var bitstreams = new List() { null, null, null, null }; + int cnt = 0; // 上传比特流数量 + for (int i = 0; i < 4; i++) + { + var bitstreamDir = Path.Combine(bitstreamsFolder, i.ToString()); + if (!Directory.Exists(bitstreamDir)) + continue; + cnt++; + + // 读取文件 + var filePath = Directory.GetFiles(bitstreamDir)[0]; + var fileBytes = await ProcessBitstream(filePath); + if (!fileBytes.IsSuccessful) return TypedResults.InternalServerError(fileBytes.Error); + bitstreams[i] = fileBytes.Value; + } + + // 下载比特流 + var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); + { + var ret = await remoteUpdater.UploadBitstreams(bitstreams[0], bitstreams[1], bitstreams[2], bitstreams[3]); + if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error); + if (!ret.Value) return TypedResults.InternalServerError("Upload MultiBitstreams failed"); + } + + if (bitstreamNum is not null) + { + var ret = await remoteUpdater.HotResetBitstream(bitstreamNum ?? 0); + if (!ret.IsSuccessful) return TypedResults.InternalServerError(ret.Error); + if (!ret.Value) return TypedResults.InternalServerError("Hot reset failed"); + } + return TypedResults.Ok(cnt); + } + catch (Exception error) + { + return TypedResults.InternalServerError(error); + } + } + + + /// + /// 热复位比特流文件 + /// + /// 设备地址 + /// 设备端口 + /// 比特流编号 + /// 操作结果 + [HttpPost("HotResetBitstream")] + [EnableCors("Users")] + [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask HotResetBitstream(string address, int port, int bitstreamNum) + { + var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); + var ret = await remoteUpdater.HotResetBitstream(bitstreamNum); + + if (ret.IsSuccessful) + { + logger.Info($"Device {address} Update bitstream successfully"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + + /// + /// [TODO:description] + /// + /// [TODO:parameter] + /// [TODO:parameter] + /// [TODO:return] + [HttpPost("GetFirmwareVersion")] + [EnableCors("Users")] + [ProducesResponseType(typeof(UInt32), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ArgumentException), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(Exception), StatusCodes.Status500InternalServerError)] + public async ValueTask GetFirmwareVersion(string address, int port) + { + var remoteUpdater = new RemoteUpdateClient.RemoteUpdater(address, port); + var ret = await remoteUpdater.GetVersion(); + + if (ret.IsSuccessful) + { + logger.Info($"Device {address} get firmware version successfully"); + return TypedResults.Ok(ret.Value); + } + else + { + logger.Error(ret.Error); + return TypedResults.InternalServerError(ret.Error); + } + } + +} diff --git a/server/src/Controllers/UDPController.cs b/server/src/Controllers/UDPController.cs new file mode 100644 index 0000000..804ad5c --- /dev/null +++ b/server/src/Controllers/UDPController.cs @@ -0,0 +1,133 @@ +using System.Net; +using Common; +using Microsoft.AspNetCore.Mvc; +using Newtonsoft.Json; +using WebProtocol; + +namespace server.Controllers; + +/// +/// UDP API +/// +[ApiController] +[Route("api/[controller]")] +public class UDPController : ControllerBase +{ + private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); + + private const string LOCALHOST = "127.0.0.1"; + + /// + /// 页面 + /// + [HttpGet] + public string Index() + { + return "This is UDP Controller"; + } + + /// + /// 发送字符串 + /// + /// IPV4 或者 IPV6 地址 + /// 设备端口号 + /// 发送的文本 + /// 发送成功 + /// 发送失败 + [HttpPost("SendString")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendString(string address = LOCALHOST, int port = 1234, string text = "Hello Server!") + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendStringAsync(endPoint, [text]); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + /// + /// 发送二进制数据 + /// + /// IPV4 或者 IPV6 地址 + /// 设备端口号 + /// 16进制文本 + [HttpPost("SendBytes")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendBytes(string address, int port, string bytes) + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendBytesAsync(endPoint, Number.StringToBytes(bytes)); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + + /// + /// 发送地址包 + /// + /// IP地址 + /// UDP 端口号 + /// 地址包选项 + [HttpPost("SendAddrPackage")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendAddrPackage( + string address, + int port, + [FromBody] SendAddrPackOptions opts) + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts)); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + /// + /// 发送数据包 + /// + /// IP地址 + /// UDP 端口号 + /// 16进制数据 + [HttpPost("SendDataPackage")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask SendDataPackage(string address, int port, string data) + { + var endPoint = new IPEndPoint(IPAddress.Parse(address), port); + var ret = await UDPClientPool.SendDataPackAsync(endPoint, + new WebProtocol.SendDataPackage(Number.StringToBytes(data))); + + if (ret) { return TypedResults.Ok(); } + else { return TypedResults.InternalServerError(); } + } + + /// + /// 获取指定IP地址接受的数据列表 + /// + /// IP地址 + [HttpGet("GetRecvDataArray")] + [ProducesResponseType(typeof(List), StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask GetRecvDataArray(string address) + { + var ret = await MsgBus.UDPServer.GetDataArrayAsync(address); + + if (ret.HasValue) + { + var dataJson = JsonConvert.SerializeObject(ret.Value); + logger.Debug($"Get Receive Successfully: {dataJson}"); + + return TypedResults.Ok(ret.Value); + } + else + { + logger.Debug("Get Receive Failed"); + return TypedResults.InternalServerError(); + } + } + +} diff --git a/server/src/H264Encoder.cs b/server/src/H264Encoder.cs deleted file mode 100644 index e69de29..0000000 diff --git a/server/src/H264MediaSource.cs b/server/src/H264MediaSource.cs deleted file mode 100644 index e69de29..0000000 diff --git a/server/src/JtagClient.cs b/server/src/JtagClient.cs index b364c89..9f39369 100644 --- a/server/src/JtagClient.cs +++ b/server/src/JtagClient.cs @@ -776,9 +776,9 @@ public class Jtag /// - /// [TODO:description] + /// 边界扫描 /// - /// [TODO:return] + /// 返回所有引脚边界扫描结果 public async ValueTask> BoundaryScan() { var paser = new BsdlParser.Parser(); @@ -824,9 +824,9 @@ public class Jtag } /// - /// [TODO:description] + /// 执行边界扫描并返回逻辑端口的状态 /// - /// [TODO:return] + /// 包含逻辑端口状态的字典,键为端口ID,值为布尔状态 public async ValueTask>> BoundaryScanLogicalPorts() { var bitArray = await BoundaryScan(); @@ -846,22 +846,22 @@ public class Jtag } /// - /// [TODO:description] + /// 设置JTAG的运行速度。 /// - /// [TODO:parameter] - /// [TODO:return] + /// 运行速度值。 + /// 指示操作是否成功的异步结果。 public async ValueTask> SetSpeed(UInt32 speed) { // Clear Data await MsgBus.UDPServer.ClearUDPData(this.address); logger.Trace($"Clear up udp server {this.address} receive data"); - + var ret = await WriteFIFO( JtagAddr.SPEED_CTRL, (speed << 16) | speed, JtagState.CMD_EXEC_FINISH, JtagState.CMD_EXEC_FINISH); - - if (!ret.IsSuccessful) return new (ret.Error); + + if (!ret.IsSuccessful) return new(ret.Error); return ret.Value; } } diff --git a/server/src/DDSClient.cs b/server/src/Peripherals/DDSClient.cs similarity index 99% rename from server/src/DDSClient.cs rename to server/src/Peripherals/DDSClient.cs index 4ecdb13..55a9ebe 100644 --- a/server/src/DDSClient.cs +++ b/server/src/Peripherals/DDSClient.cs @@ -1,7 +1,7 @@ using System.Net; using DotNext; -namespace DDSClient; +namespace Peripherals.DDSClient; static class DDSAddr { diff --git a/server/src/Peripherals/MatrixKeyClient.cs b/server/src/Peripherals/MatrixKeyClient.cs new file mode 100644 index 0000000..abd830f --- /dev/null +++ b/server/src/Peripherals/MatrixKeyClient.cs @@ -0,0 +1,89 @@ +using System.Collections; +using System.Net; +using DotNext; + +namespace Peripherals.MatrixKeyClient; + +class MatrixKeyAddr +{ + public const UInt32 BASE = 0x10_00_00_00; + public const UInt32 KEY_ENABLE = BASE + 5; + public const UInt32 KEY_CTRL = BASE + 6; +} + +/// +/// 矩阵键盘外设类,用于控制和管理矩阵键盘的功能。 +/// +public class MatrixKey +{ + readonly int timeout; + + readonly int port; + readonly string address; + private IPEndPoint ep; + + /// + /// 构造函数,用于初始化矩阵键盘外设实例。 + /// + /// 设备的IP地址 + /// 设备的端口号 + /// 操作的超时时间(毫秒),默认为1000 + /// 无返回值。 + public MatrixKey(string address, int port, int timeout = 1000) + { + this.address = address; + this.port = port; + this.ep = new IPEndPoint(IPAddress.Parse(address), port); + this.timeout = timeout; + } + + /// + /// 启用矩阵键盘的控制功能。 + /// + /// 返回一个包含操作结果的异步任务 + public async ValueTask> EnableControl() + { + if (MsgBus.IsRunning) + await MsgBus.UDPServer.ClearUDPData(this.address); + else return new(new Exception("Message Bus not work!")); + + var ret = await UDPClientPool.WriteAddr(this.ep, MatrixKeyAddr.KEY_ENABLE, 1, this.timeout); + if (!ret.IsSuccessful) return new(ret.Error); + return ret.Value; + } + + /// + /// 禁用矩阵键盘的控制功能。 + /// + /// 返回一个包含操作结果的异步任务 + public async ValueTask> DisableControl() + { + if (MsgBus.IsRunning) + await MsgBus.UDPServer.ClearUDPData(this.address); + else return new(new Exception("Message Bus not work!")); + + var ret = await UDPClientPool.WriteAddr(this.ep, MatrixKeyAddr.KEY_ENABLE, 0, this.timeout); + if (!ret.IsSuccessful) return new(ret.Error); + return ret.Value; + } + + /// + /// 控制矩阵键盘的按键状态。 + /// + /// 表示按键状态的位数组,长度必须为16 + /// 返回一个包含操作结果的异步任务 + public async ValueTask> ControlKey(BitArray keyStates) + { + if (MsgBus.IsRunning) + await MsgBus.UDPServer.ClearUDPData(this.address); + else return new(new Exception("Message Bus not work!")); + + if (keyStates.Length != 16) return new(new ArgumentException( + $"The number of key should be 16 instead of {keyStates.Length}", nameof(keyStates))); + + var ret = await UDPClientPool.WriteAddr( + this.ep, MatrixKeyAddr.KEY_CTRL, Common.Number.BitsToNumber(keyStates).Value, this.timeout); + if (!ret.IsSuccessful) return new(ret.Error); + return ret.Value; + } +} diff --git a/server/src/VideoStreamService.cs b/server/src/VideoStreamService.cs deleted file mode 100644 index e69de29..0000000 diff --git a/src/APIClient.ts b/src/APIClient.ts index 1efd437..0cbb72b 100644 --- a/src/APIClient.ts +++ b/src/APIClient.ts @@ -8,7 +8,7 @@ /* eslint-disable */ // ReSharper disable InconsistentNaming -export class UDPClient { +export class BsdlParserClient { private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; private baseUrl: string; protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; @@ -19,25 +19,283 @@ export class UDPClient { } /** - * 页面 + * [TODO:description] + * @return [TODO:return] */ - index(): Promise { - let url_ = this.baseUrl + "/api/UDP"; + getBoundaryLogicalPorts(): Promise { + let url_ = this.baseUrl + "/api/BsdlParser/GetBoundaryLogicalPorts"; url_ = url_.replace(/[?&]$/, ""); let options_: RequestInit = { method: "GET", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processGetBoundaryLogicalPorts(_response); + }); + } + + protected processGetBoundaryLogicalPorts(response: Response): Promise { + 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 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _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(null as any); + } +} + +export class DataClient { + private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { + this.http = http ? http : window as any; + this.baseUrl = baseUrl ?? "http://localhost:5000"; + } + + /** + * 创建数据库表 + * @return 插入的记录数 + */ + createTables(): Promise { + let url_ = this.baseUrl + "/api/Data/CreateTable"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processCreateTables(_response); + }); + } + + protected processCreateTables(response: Response): Promise { + 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 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _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(null as any); + } + + /** + * 删除数据库表 + * @return 插入的记录数 + */ + dropTables(): Promise { + let url_ = this.baseUrl + "/api/Data/DropTables"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "DELETE", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processDropTables(_response); + }); + } + + protected processDropTables(response: Response): Promise { + 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 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _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(null as any); + } + + /** + * 获取所有用户 + * @return 用户列表 + */ + allUsers(): Promise { + let url_ = this.baseUrl + "/api/Data/AllUsers"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "GET", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processAllUsers(_response); + }); + } + + protected processAllUsers(response: Response): Promise { + 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 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _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(null as any); + } + + /** + * 注册新用户 + * @param name (optional) 用户名 + * @return 操作结果 + */ + signUpUser(name: string | undefined): Promise { + let url_ = this.baseUrl + "/api/Data/SignUpUser?"; + if (name === null) + throw new Error("The parameter 'name' cannot be null."); + else if (name !== undefined) + url_ += "name=" + encodeURIComponent("" + name) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/octet-stream" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processSignUpUser(_response); + }); + } + + protected processSignUpUser(response: Response): Promise { + 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 || status === 206) { + const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; + let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; + let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; + if (fileName) { + fileName = decodeURIComponent(fileName); + } else { + fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; + fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + } + return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _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(null as any); + } +} + +export class DDSClient { + private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { + this.http = http ? http : window as any; + this.baseUrl = baseUrl ?? "http://localhost:5000"; + } + + /** + * [TODO:description] + * @param address (optional) [TODO:parameter] + * @param port (optional) [TODO:parameter] + * @param channelNum (optional) [TODO:parameter] + * @param waveNum (optional) [TODO:parameter] + * @return [TODO:return] + */ + setWaveNum(address: string | undefined, port: number | undefined, channelNum: number | undefined, waveNum: number | undefined): Promise { + let url_ = this.baseUrl + "/api/DDS/SetWaveNum?"; + 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 (channelNum === null) + throw new Error("The parameter 'channelNum' cannot be null."); + else if (channelNum !== undefined) + url_ += "channelNum=" + encodeURIComponent("" + channelNum) + "&"; + if (waveNum === null) + throw new Error("The parameter 'waveNum' cannot be null."); + else if (waveNum !== undefined) + url_ += "waveNum=" + encodeURIComponent("" + waveNum) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", headers: { "Accept": "application/json" } }; return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processIndex(_response); + return this.processSetWaveNum(_response); }); } - protected processIndex(response: Response): Promise { + protected processSetWaveNum(response: Response): Promise { 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) { @@ -48,23 +306,39 @@ export class UDPClient { return result200; }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ArgumentException.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); + }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { return throwException("An unexpected server error occurred.", status, _responseText, _headers); }); } - return Promise.resolve(null as any); + return Promise.resolve(null as any); } /** - * 发送字符串 - * @param address (optional) IPV4 或者 IPV6 地址 - * @param port (optional) 设备端口号 - * @param text (optional) 发送的文本 - * @return 发送成功 + * [TODO:description] + * @param address (optional) [TODO:parameter] + * @param port (optional) [TODO:parameter] + * @param channelNum (optional) [TODO:parameter] + * @param waveNum (optional) [TODO:parameter] + * @param step (optional) [TODO:parameter] + * @return [TODO:return] */ - sendString(address: string | undefined, port: number | undefined, text: string | undefined): Promise { - let url_ = this.baseUrl + "/api/UDP/SendString?"; + setFreq(address: string | undefined, port: number | undefined, channelNum: number | undefined, waveNum: number | undefined, step: number | undefined): Promise { + let url_ = this.baseUrl + "/api/DDS/SetFreq?"; if (address === null) throw new Error("The parameter 'address' cannot be null."); else if (address !== undefined) @@ -73,249 +347,141 @@ export class UDPClient { 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) + "&"; + if (channelNum === null) + throw new Error("The parameter 'channelNum' cannot be null."); + else if (channelNum !== undefined) + url_ += "channelNum=" + encodeURIComponent("" + channelNum) + "&"; + if (waveNum === null) + throw new Error("The parameter 'waveNum' cannot be null."); + else if (waveNum !== undefined) + url_ += "waveNum=" + encodeURIComponent("" + waveNum) + "&"; + if (step === null) + throw new Error("The parameter 'step' cannot be null."); + else if (step !== undefined) + url_ += "step=" + encodeURIComponent("" + step) + "&"; 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 { - 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(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 { - 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 { - 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(null as any); - } - - /** - * 发送地址包 - * @param address (optional) IP地址 - * @param port (optional) UDP 端口号 - * @param opts 地址包选项 - */ - sendAddrPackage(address: string | undefined, port: number | undefined, opts: SendAddrPackOptions): Promise { - 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 { - 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(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 { - 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 { - 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(null as any); - } - - /** - * 获取指定IP地址接受的数据列表 - * @param address (optional) IP地址 - */ - getRecvDataArray(address: string | undefined): Promise { - 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); + return this.processSetFreq(_response); }); } - protected processGetRecvDataArray(response: Response): Promise { + protected processSetFreq(response: Response): Promise { 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 = null; - } + result200 = resultData200 !== undefined ? resultData200 : null; + return result200; }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ArgumentException.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); + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); }); } else if (status !== 200 && status !== 204) { return response.text().then((_responseText) => { return throwException("An unexpected server error occurred.", status, _responseText, _headers); }); } - return Promise.resolve(null as any); + return Promise.resolve(null as any); + } + + /** + * [TODO:description] + * @param address (optional) [TODO:parameter] + * @param port (optional) [TODO:parameter] + * @param channelNum (optional) [TODO:parameter] + * @param waveNum (optional) [TODO:parameter] + * @param phase (optional) [TODO:parameter] + * @return [TODO:return] + */ + setPhase(address: string | undefined, port: number | undefined, channelNum: number | undefined, waveNum: number | undefined, phase: number | undefined): Promise { + let url_ = this.baseUrl + "/api/DDS/SetPhase?"; + 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 (channelNum === null) + throw new Error("The parameter 'channelNum' cannot be null."); + else if (channelNum !== undefined) + url_ += "channelNum=" + encodeURIComponent("" + channelNum) + "&"; + if (waveNum === null) + throw new Error("The parameter 'waveNum' cannot be null."); + else if (waveNum !== undefined) + url_ += "waveNum=" + encodeURIComponent("" + waveNum) + "&"; + if (phase === null) + throw new Error("The parameter 'phase' cannot be null."); + else if (phase !== undefined) + url_ += "phase=" + encodeURIComponent("" + phase) + "&"; + url_ = url_.replace(/[?&]$/, ""); + + let options_: RequestInit = { + method: "POST", + headers: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processSetPhase(_response); + }); + } + + protected processSetPhase(response: Response): Promise { + 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 : null; + + return result200; + }); + } else if (status === 400) { + return response.text().then((_responseText) => { + let result400: any = null; + let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result400 = ArgumentException.fromJS(resultData400); + return throwException("A server side error occurred.", status, _responseText, _headers, result400); + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); } } @@ -702,14 +868,6 @@ export class JtagClient { } return result200; }); - } else if (status === 400) { - return response.text().then((_responseText) => { - let result400: any = null; - let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result400 = resultData400 !== undefined ? resultData400 : null; - - return throwException("A server side error occurred.", status, _responseText, _headers, result400); - }); } else if (status === 500) { return response.text().then((_responseText) => { let result500: any = null; @@ -771,14 +929,6 @@ export class JtagClient { return result200; }); - } else if (status === 400) { - return response.text().then((_responseText) => { - let result400: any = null; - let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result400 = resultData400 !== undefined ? resultData400 : null; - - return throwException("A server side error occurred.", status, _responseText, _headers, result400); - }); } else if (status === 500) { return response.text().then((_responseText) => { let result500: any = null; @@ -795,6 +945,171 @@ export class JtagClient { } } +export class MatrixKeyClient { + private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { + this.http = http ? http : window as any; + this.baseUrl = baseUrl ?? "http://localhost:5000"; + } + + enabelMatrixKey(address: string | undefined, port: number | undefined): Promise { + let url_ = this.baseUrl + "/api/MatrixKey/EnabelMatrixKey?"; + 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: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processEnabelMatrixKey(_response); + }); + } + + protected processEnabelMatrixKey(response: Response): Promise { + 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 : null; + + return result200; + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + disableMatrixKey(address: string | undefined, port: number | undefined): Promise { + let url_ = this.baseUrl + "/api/MatrixKey/DisableMatrixKey?"; + 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: { + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processDisableMatrixKey(_response); + }); + } + + protected processDisableMatrixKey(response: Response): Promise { + 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 : null; + + return result200; + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } + + setMatrixKeyStatus(address: string | undefined, port: number | undefined, keyStates: boolean[]): Promise { + let url_ = this.baseUrl + "/api/MatrixKey/SetMatrixKeyStatus?"; + 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(keyStates); + + let options_: RequestInit = { + body: content_, + method: "GET", + headers: { + "Content-Type": "application/json", + "Accept": "application/json" + } + }; + + return this.http.fetch(url_, options_).then((_response: Response) => { + return this.processSetMatrixKeyStatus(_response); + }); + } + + protected processSetMatrixKeyStatus(response: Response): Promise { + 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 : null; + + return result200; + }); + } else if (status === 500) { + return response.text().then((_responseText) => { + let result500: any = null; + let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result500 = Exception.fromJS(resultData500); + return throwException("A server side error occurred.", status, _responseText, _headers, result500); + }); + } else if (status !== 200 && status !== 204) { + return response.text().then((_responseText) => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + }); + } + return Promise.resolve(null as any); + } +} + export class RemoteUpdateClient { private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; private baseUrl: string; @@ -1136,7 +1451,7 @@ export class RemoteUpdateClient { } } -export class DDSClient { +export class UDPClient { private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; private baseUrl: string; protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; @@ -1147,466 +1462,415 @@ export class DDSClient { } /** - * [TODO:description] - * @param address (optional) [TODO:parameter] - * @param port (optional) [TODO:parameter] - * @param channelNum (optional) [TODO:parameter] - * @param waveNum (optional) [TODO:parameter] - * @return [TODO:return] + * 页面 */ - setWaveNum(address: string | undefined, port: number | undefined, channelNum: number | undefined, waveNum: number | undefined): Promise { - let url_ = this.baseUrl + "/api/DDS/SetWaveNum?"; - 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 (channelNum === null) - throw new Error("The parameter 'channelNum' cannot be null."); - else if (channelNum !== undefined) - url_ += "channelNum=" + encodeURIComponent("" + channelNum) + "&"; - if (waveNum === null) - throw new Error("The parameter 'waveNum' cannot be null."); - else if (waveNum !== undefined) - url_ += "waveNum=" + encodeURIComponent("" + waveNum) + "&"; - url_ = url_.replace(/[?&]$/, ""); - - let options_: RequestInit = { - method: "POST", - headers: { - "Accept": "application/json" - } - }; - - return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processSetWaveNum(_response); - }); - } - - protected processSetWaveNum(response: Response): Promise { - 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 : null; - - return result200; - }); - } else if (status === 400) { - return response.text().then((_responseText) => { - let result400: any = null; - let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result400 = ArgumentException.fromJS(resultData400); - return throwException("A server side error occurred.", status, _responseText, _headers, result400); - }); - } else if (status === 500) { - return response.text().then((_responseText) => { - let result500: any = null; - let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result500 = Exception.fromJS(resultData500); - return throwException("A server side error occurred.", status, _responseText, _headers, result500); - }); - } else if (status !== 200 && status !== 204) { - return response.text().then((_responseText) => { - return throwException("An unexpected server error occurred.", status, _responseText, _headers); - }); - } - return Promise.resolve(null as any); - } - - /** - * [TODO:description] - * @param address (optional) [TODO:parameter] - * @param port (optional) [TODO:parameter] - * @param channelNum (optional) [TODO:parameter] - * @param waveNum (optional) [TODO:parameter] - * @param step (optional) [TODO:parameter] - * @return [TODO:return] - */ - setFreq(address: string | undefined, port: number | undefined, channelNum: number | undefined, waveNum: number | undefined, step: number | undefined): Promise { - let url_ = this.baseUrl + "/api/DDS/SetFreq?"; - 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 (channelNum === null) - throw new Error("The parameter 'channelNum' cannot be null."); - else if (channelNum !== undefined) - url_ += "channelNum=" + encodeURIComponent("" + channelNum) + "&"; - if (waveNum === null) - throw new Error("The parameter 'waveNum' cannot be null."); - else if (waveNum !== undefined) - url_ += "waveNum=" + encodeURIComponent("" + waveNum) + "&"; - if (step === null) - throw new Error("The parameter 'step' cannot be null."); - else if (step !== undefined) - url_ += "step=" + encodeURIComponent("" + step) + "&"; - url_ = url_.replace(/[?&]$/, ""); - - let options_: RequestInit = { - method: "POST", - headers: { - "Accept": "application/json" - } - }; - - return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processSetFreq(_response); - }); - } - - protected processSetFreq(response: Response): Promise { - 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 : null; - - return result200; - }); - } else if (status === 400) { - return response.text().then((_responseText) => { - let result400: any = null; - let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result400 = ArgumentException.fromJS(resultData400); - return throwException("A server side error occurred.", status, _responseText, _headers, result400); - }); - } else if (status === 500) { - return response.text().then((_responseText) => { - let result500: any = null; - let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result500 = Exception.fromJS(resultData500); - return throwException("A server side error occurred.", status, _responseText, _headers, result500); - }); - } else if (status !== 200 && status !== 204) { - return response.text().then((_responseText) => { - return throwException("An unexpected server error occurred.", status, _responseText, _headers); - }); - } - return Promise.resolve(null as any); - } - - /** - * [TODO:description] - * @param address (optional) [TODO:parameter] - * @param port (optional) [TODO:parameter] - * @param channelNum (optional) [TODO:parameter] - * @param waveNum (optional) [TODO:parameter] - * @param phase (optional) [TODO:parameter] - * @return [TODO:return] - */ - setPhase(address: string | undefined, port: number | undefined, channelNum: number | undefined, waveNum: number | undefined, phase: number | undefined): Promise { - let url_ = this.baseUrl + "/api/DDS/SetPhase?"; - 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 (channelNum === null) - throw new Error("The parameter 'channelNum' cannot be null."); - else if (channelNum !== undefined) - url_ += "channelNum=" + encodeURIComponent("" + channelNum) + "&"; - if (waveNum === null) - throw new Error("The parameter 'waveNum' cannot be null."); - else if (waveNum !== undefined) - url_ += "waveNum=" + encodeURIComponent("" + waveNum) + "&"; - if (phase === null) - throw new Error("The parameter 'phase' cannot be null."); - else if (phase !== undefined) - url_ += "phase=" + encodeURIComponent("" + phase) + "&"; - url_ = url_.replace(/[?&]$/, ""); - - let options_: RequestInit = { - method: "POST", - headers: { - "Accept": "application/json" - } - }; - - return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processSetPhase(_response); - }); - } - - protected processSetPhase(response: Response): Promise { - 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 : null; - - return result200; - }); - } else if (status === 400) { - return response.text().then((_responseText) => { - let result400: any = null; - let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result400 = ArgumentException.fromJS(resultData400); - return throwException("A server side error occurred.", status, _responseText, _headers, result400); - }); - } else if (status === 500) { - return response.text().then((_responseText) => { - let result500: any = null; - let resultData500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); - result500 = Exception.fromJS(resultData500); - return throwException("A server side error occurred.", status, _responseText, _headers, result500); - }); - } else if (status !== 200 && status !== 204) { - return response.text().then((_responseText) => { - return throwException("An unexpected server error occurred.", status, _responseText, _headers); - }); - } - return Promise.resolve(null as any); - } -} - -export class BsdlParserClient { - private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; - private baseUrl: string; - protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; - - constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { - this.http = http ? http : window as any; - this.baseUrl = baseUrl ?? "http://localhost:5000"; - } - - getBoundaryLogicalPorts(): Promise { - let url_ = this.baseUrl + "/api/BsdlParser/GetBoundaryLogicalPorts"; + index(): Promise { + let url_ = this.baseUrl + "/api/UDP"; url_ = url_.replace(/[?&]$/, ""); let options_: RequestInit = { method: "GET", headers: { - "Accept": "application/octet-stream" + "Accept": "application/json" } }; return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processGetBoundaryLogicalPorts(_response); + return this.processIndex(_response); }); } - protected processGetBoundaryLogicalPorts(response: Response): Promise { + protected processIndex(response: Response): Promise { 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 || status === 206) { - const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; - let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; - if (fileName) { - fileName = decodeURIComponent(fileName); - } else { - fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; - } - return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + 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 : 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(null as any); - } -} - -export class DataClient { - private http: { fetch(url: RequestInfo, init?: RequestInit): Promise }; - private baseUrl: string; - protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; - - constructor(baseUrl?: string, http?: { fetch(url: RequestInfo, init?: RequestInit): Promise }) { - this.http = http ? http : window as any; - this.baseUrl = baseUrl ?? "http://localhost:5000"; + return Promise.resolve(null as any); } /** - * 创建数据库表 - * @return 插入的记录数 + * 发送字符串 + * @param address (optional) IPV4 或者 IPV6 地址 + * @param port (optional) 设备端口号 + * @param text (optional) 发送的文本 + * @return 发送成功 */ - createTables(): Promise { - let url_ = this.baseUrl + "/api/Data/CreateTable"; + sendString(address: string | undefined, port: number | undefined, text: string | undefined): Promise { + 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: { - "Accept": "application/octet-stream" } }; return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processCreateTables(_response); + return this.processSendString(_response); }); } - protected processCreateTables(response: Response): Promise { + protected processSendString(response: Response): Promise { 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 || status === 206) { - const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; - let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; - if (fileName) { - fileName = decodeURIComponent(fileName); - } else { - fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; - } - return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + 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(null as any); + return Promise.resolve(null as any); } /** - * 删除数据库表 - * @return 插入的记录数 + * 发送二进制数据 + * @param address (optional) IPV4 或者 IPV6 地址 + * @param port (optional) 设备端口号 + * @param bytes (optional) 16进制文本 */ - dropTables(): Promise { - let url_ = this.baseUrl + "/api/Data/DropTables"; + sendBytes(address: string | undefined, port: number | undefined, bytes: string | undefined): Promise { + 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: "DELETE", + method: "POST", headers: { - "Accept": "application/octet-stream" } }; return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processDropTables(_response); + return this.processSendBytes(_response); }); } - protected processDropTables(response: Response): Promise { + protected processSendBytes(response: Response): Promise { 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 || status === 206) { - const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; - let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; - if (fileName) { - fileName = decodeURIComponent(fileName); - } else { - fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; - } - return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + 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(null as any); + return Promise.resolve(null as any); } /** - * 获取所有用户 - * @return 用户列表 + * 发送地址包 + * @param address (optional) IP地址 + * @param port (optional) UDP 端口号 + * @param opts 地址包选项 */ - allUsers(): Promise { - let url_ = this.baseUrl + "/api/Data/AllUsers"; + sendAddrPackage(address: string | undefined, port: number | undefined, opts: SendAddrPackOptions): Promise { + 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 { + 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(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 { + 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 { + 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(null as any); + } + + /** + * 获取指定IP地址接受的数据列表 + * @param address (optional) IP地址 + */ + getRecvDataArray(address: string | undefined): Promise { + 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/octet-stream" + "Accept": "application/json" } }; return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processAllUsers(_response); + return this.processGetRecvDataArray(_response); }); } - protected processAllUsers(response: Response): Promise { + protected processGetRecvDataArray(response: Response): Promise { 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 || status === 206) { - const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; - let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; - if (fileName) { - fileName = decodeURIComponent(fileName); - } else { - fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; + 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)); } - return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _headers }; }); + else { + result200 = 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(null as any); + return Promise.resolve(null as any); } +} - /** - * 注册新用户 - * @param name (optional) 用户名 - * @return 操作结果 - */ - signUpUser(name: string | undefined): Promise { - let url_ = this.baseUrl + "/api/Data/SignUpUser?"; - if (name === null) - throw new Error("The parameter 'name' cannot be null."); - else if (name !== undefined) - url_ += "name=" + encodeURIComponent("" + name) + "&"; - url_ = url_.replace(/[?&]$/, ""); +export class Exception implements IException { + message?: string; + innerException?: Exception | undefined; + source?: string | undefined; + stackTrace?: string | undefined; - let options_: RequestInit = { - method: "POST", - headers: { - "Accept": "application/octet-stream" + constructor(data?: IException) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; } - }; - - return this.http.fetch(url_, options_).then((_response: Response) => { - return this.processSignUpUser(_response); - }); - } - - protected processSignUpUser(response: Response): Promise { - 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 || status === 206) { - const contentDisposition = response.headers ? response.headers.get("content-disposition") : undefined; - let fileNameMatch = contentDisposition ? /filename\*=(?:(\\?['"])(.*?)\1|(?:[^\s]+'.*?')?([^;\n]*))/g.exec(contentDisposition) : undefined; - let fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[3] || fileNameMatch[2] : undefined; - if (fileName) { - fileName = decodeURIComponent(fileName); - } else { - fileNameMatch = contentDisposition ? /filename="?([^"]*?)"?(;|$)/g.exec(contentDisposition) : undefined; - fileName = fileNameMatch && fileNameMatch.length > 1 ? fileNameMatch[1] : undefined; - } - return response.blob().then(blob => { return { fileName: fileName, data: blob, status: status, headers: _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(null as any); } + + init(_data?: any) { + if (_data) { + this.message = _data["Message"]; + this.innerException = _data["InnerException"] ? Exception.fromJS(_data["InnerException"]) : undefined; + this.source = _data["Source"]; + this.stackTrace = _data["StackTrace"]; + } + } + + static fromJS(data: any): Exception { + data = typeof data === 'object' ? data : {}; + let result = new Exception(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["Message"] = this.message; + data["InnerException"] = this.innerException ? this.innerException.toJSON() : undefined; + data["Source"] = this.source; + data["StackTrace"] = this.stackTrace; + return data; + } +} + +export interface IException { + message?: string; + innerException?: Exception | undefined; + source?: string | undefined; + stackTrace?: string | undefined; +} + +export class SystemException extends Exception implements ISystemException { + + constructor(data?: ISystemException) { + super(data); + } + + init(_data?: any) { + super.init(_data); + } + + static fromJS(data: any): SystemException { + data = typeof data === 'object' ? data : {}; + let result = new SystemException(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + super.toJSON(data); + return data; + } +} + +export interface ISystemException extends IException { +} + +export class ArgumentException extends SystemException implements IArgumentException { + paramName?: string | undefined; + + constructor(data?: IArgumentException) { + super(data); + } + + init(_data?: any) { + super.init(_data); + if (_data) { + this.message = _data["Message"]; + this.paramName = _data["ParamName"]; + } + } + + static fromJS(data: any): ArgumentException { + data = typeof data === 'object' ? data : {}; + let result = new ArgumentException(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["Message"] = this.message; + data["ParamName"] = this.paramName; + super.toJSON(data); + return data; + } +} + +export interface IArgumentException extends ISystemException { + message?: string; + paramName?: string | undefined; } /** Package options which to send address to read or write */ @@ -1743,117 +2007,6 @@ export interface IUDPData { hasRead?: boolean; } -export class Exception implements IException { - message?: string; - innerException?: Exception | undefined; - source?: string | undefined; - stackTrace?: string | undefined; - - constructor(data?: IException) { - if (data) { - for (var property in data) { - if (data.hasOwnProperty(property)) - (this)[property] = (data)[property]; - } - } - } - - init(_data?: any) { - if (_data) { - this.message = _data["Message"]; - this.innerException = _data["InnerException"] ? Exception.fromJS(_data["InnerException"]) : undefined; - this.source = _data["Source"]; - this.stackTrace = _data["StackTrace"]; - } - } - - static fromJS(data: any): Exception { - data = typeof data === 'object' ? data : {}; - let result = new Exception(); - result.init(data); - return result; - } - - toJSON(data?: any) { - data = typeof data === 'object' ? data : {}; - data["Message"] = this.message; - data["InnerException"] = this.innerException ? this.innerException.toJSON() : undefined; - data["Source"] = this.source; - data["StackTrace"] = this.stackTrace; - return data; - } -} - -export interface IException { - message?: string; - innerException?: Exception | undefined; - source?: string | undefined; - stackTrace?: string | undefined; -} - -export class SystemException extends Exception implements ISystemException { - - constructor(data?: ISystemException) { - super(data); - } - - init(_data?: any) { - super.init(_data); - } - - static fromJS(data: any): SystemException { - data = typeof data === 'object' ? data : {}; - let result = new SystemException(); - result.init(data); - return result; - } - - toJSON(data?: any) { - data = typeof data === 'object' ? data : {}; - super.toJSON(data); - return data; - } -} - -export interface ISystemException extends IException { -} - -export class ArgumentException extends SystemException implements IArgumentException { - paramName?: string | undefined; - - constructor(data?: IArgumentException) { - super(data); - } - - init(_data?: any) { - super.init(_data); - if (_data) { - this.message = _data["Message"]; - this.paramName = _data["ParamName"]; - } - } - - static fromJS(data: any): ArgumentException { - data = typeof data === 'object' ? data : {}; - let result = new ArgumentException(); - result.init(data); - return result; - } - - toJSON(data?: any) { - data = typeof data === 'object' ? data : {}; - data["Message"] = this.message; - data["ParamName"] = this.paramName; - super.toJSON(data); - return data; - } -} - -export interface IArgumentException extends ISystemException { - message?: string; - paramName?: string | undefined; -} - export interface FileParameter { data: any; fileName: string;