feat: 使用静态arp处理通信
This commit is contained in:
		@@ -433,8 +433,38 @@ public static class Arp
 | 
			
		||||
            return Environment.UserName == "root" || (Environment.GetEnvironmentVariable("USER") == "root");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 检查指定 IP 是否存在对应的 MAC,如果不存在则删除原有 ARP 记录并新增
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="ipAddress">IP 地址</param>
 | 
			
		||||
    /// <param name="macAddress">MAC 地址</param>
 | 
			
		||||
    /// <param name="interfaceName">网络接口名称(可选)</param>
 | 
			
		||||
    /// <returns>是否成功</returns>
 | 
			
		||||
    public static async Task<bool> CheckOrAddAsync(string ipAddress, string macAddress, string? interfaceName = null)
 | 
			
		||||
    {
 | 
			
		||||
        if (string.IsNullOrWhiteSpace(ipAddress))
 | 
			
		||||
            throw new ArgumentException("IP 地址不能为空", nameof(ipAddress));
 | 
			
		||||
        if (string.IsNullOrWhiteSpace(macAddress))
 | 
			
		||||
            throw new ArgumentException("MAC 地址不能为空", nameof(macAddress));
 | 
			
		||||
 | 
			
		||||
        var entry = await GetArpEntryAsync(ipAddress);
 | 
			
		||||
        if (entry != null && string.Equals(entry.MacAddress, macAddress, StringComparison.OrdinalIgnoreCase))
 | 
			
		||||
        {
 | 
			
		||||
            // 已存在且 MAC 匹配,无需操作
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 若存在但 MAC 不匹配,先删除
 | 
			
		||||
        if (entry != null)
 | 
			
		||||
        {
 | 
			
		||||
            await DeleteArpEntryAsync(ipAddress, interfaceName);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 新增 ARP 记录
 | 
			
		||||
        return await AddArpEntryAsync(ipAddress, macAddress, interfaceName);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// ARP 记录条目
 | 
			
		||||
/// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -207,7 +207,7 @@ public class DataController : ControllerBase
 | 
			
		||||
    [ProducesResponseType(typeof(Database.Board), StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    public IActionResult GetAvailableBoard(int durationHours = 1)
 | 
			
		||||
    public async ValueTask<IActionResult> GetAvailableBoard(int durationHours = 1)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -227,7 +227,13 @@ public class DataController : ControllerBase
 | 
			
		||||
            if (!boardOpt.HasValue)
 | 
			
		||||
                return NotFound("没有可用的实验板");
 | 
			
		||||
 | 
			
		||||
            return Ok(boardOpt.Value);
 | 
			
		||||
            var boardInfo = boardOpt.Value;
 | 
			
		||||
            if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr)))
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"无法配置ARP,实验板可能会无法连接");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return Ok(boardInfo);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
@@ -278,7 +284,7 @@ public class DataController : ControllerBase
 | 
			
		||||
    [ProducesResponseType(typeof(Database.Board), StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status404NotFound)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    public IActionResult GetBoardByID(Guid id)
 | 
			
		||||
    public async Task<IActionResult> GetBoardByID(Guid id)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
@@ -288,7 +294,14 @@ public class DataController : ControllerBase
 | 
			
		||||
                return StatusCode(StatusCodes.Status500InternalServerError, "数据库操作失败");
 | 
			
		||||
            if (!ret.Value.HasValue)
 | 
			
		||||
                return NotFound("未找到对应的实验板");
 | 
			
		||||
            return Ok(ret.Value.Value);
 | 
			
		||||
 | 
			
		||||
            var boardInfo = ret.Value.Value;
 | 
			
		||||
            if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr)))
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"无法配置ARP,实验板可能会无法连接");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return Ok(boardInfo);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
@@ -372,5 +385,59 @@ public class DataController : ControllerBase
 | 
			
		||||
            return StatusCode(StatusCodes.Status500InternalServerError, "获取失败,请稍后重试");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 更新板卡名称(管理员权限)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Authorize("Admin")]
 | 
			
		||||
    [HttpPost("UpdateBoardName")]
 | 
			
		||||
    [EnableCors("Users")]
 | 
			
		||||
    [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    public IActionResult UpdateBoardName(Guid boardId, string newName)
 | 
			
		||||
    {
 | 
			
		||||
        if (boardId == Guid.Empty)
 | 
			
		||||
            return BadRequest("板子Guid不能为空");
 | 
			
		||||
        if (string.IsNullOrWhiteSpace(newName))
 | 
			
		||||
            return BadRequest("新名称不能为空");
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            using var db = new Database.AppDataConnection();
 | 
			
		||||
            var result = db.UpdateBoardName(boardId, newName);
 | 
			
		||||
            return Ok(result);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ex, "更新板卡名称时发生异常");
 | 
			
		||||
            return StatusCode(StatusCodes.Status500InternalServerError, "更新失败,请稍后重试");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 更新板卡状态(管理员权限)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [Authorize("Admin")]
 | 
			
		||||
    [HttpPost("UpdateBoardStatus")]
 | 
			
		||||
    [EnableCors("Users")]
 | 
			
		||||
    [ProducesResponseType(typeof(int), StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    public IActionResult UpdateBoardStatus(Guid boardId, Database.Board.BoardStatus newStatus)
 | 
			
		||||
    {
 | 
			
		||||
        if (boardId == Guid.Empty)
 | 
			
		||||
            return BadRequest("板子Guid不能为空");
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            using var db = new Database.AppDataConnection();
 | 
			
		||||
            var result = db.UpdateBoardStatus(boardId, newStatus);
 | 
			
		||||
            return Ok(result);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ex, "更新板卡状态时发生异常");
 | 
			
		||||
            return StatusCode(StatusCodes.Status500InternalServerError, "更新失败,请稍后重试");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.GetHostIP();
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -63,6 +67,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.GetBoardIP();
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -93,6 +101,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.GetHostMAC();
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -123,6 +135,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.GetBoardMAC();
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -153,6 +169,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var hostIPResult = await netConfig.GetHostIP();
 | 
			
		||||
            var boardIPResult = await netConfig.GetBoardIP();
 | 
			
		||||
@@ -237,6 +257,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        {
 | 
			
		||||
            // 创建网络配置客户端
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.SetHostIP(hostIpAddress);
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -276,6 +300,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        {
 | 
			
		||||
            // 创建网络配置客户端
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.SetBoardIP(newIpAddress);
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -316,6 +344,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        {
 | 
			
		||||
            // 创建网络配置客户端
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.SetHostMAC(macBytes);
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -367,6 +399,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
                return StatusCode(StatusCodes.Status500InternalServerError, "无法获取本机IP地址");
 | 
			
		||||
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.SetHostIP(ip);
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -411,6 +447,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
 | 
			
		||||
            // 创建网络配置客户端
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.SetHostMAC(macBytes);
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
@@ -451,6 +491,10 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        {
 | 
			
		||||
            // 创建网络配置客户端
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            if (!(await netConfig.Init()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception($"无法配置ARP");
 | 
			
		||||
            }
 | 
			
		||||
            var result = await netConfig.SetBoardMAC(macBytes);
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,8 @@ public class NetConfig
 | 
			
		||||
    readonly string address;
 | 
			
		||||
    private IPEndPoint ep;
 | 
			
		||||
 | 
			
		||||
    const string DEFAULT_BOARD_MAC = "12:34:56:78:9a:bc";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Initialize NetConfig client
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -44,6 +46,15 @@ public class NetConfig
 | 
			
		||||
        this.timeout = timeout;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// [TODO:description]
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>[TODO:return]</returns>
 | 
			
		||||
    public async ValueTask<bool> Init()
 | 
			
		||||
    {
 | 
			
		||||
        return await Arp.CheckOrAddAsync(this.address, DEFAULT_BOARD_MAC);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Set host IP address
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -55,11 +66,11 @@ public class NetConfig
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ipBytes = ip.GetAddressBytes();
 | 
			
		||||
 | 
			
		||||
@@ -106,11 +117,11 @@ public class NetConfig
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ipBytes = ip.GetAddressBytes();
 | 
			
		||||
 | 
			
		||||
@@ -160,13 +171,13 @@ public class NetConfig
 | 
			
		||||
 | 
			
		||||
        // 清除UDP服务器接收缓冲区
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ret = await UDPClientPool.WriteAddrSeq(this.ep, this.taskID, NetConfigAddr.HOST_MAC, macAddress, this.timeout);
 | 
			
		||||
        if (!ret.IsSuccessful)
 | 
			
		||||
@@ -214,13 +225,13 @@ public class NetConfig
 | 
			
		||||
 | 
			
		||||
        // 清除UDP服务器接收缓冲区
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ret = await UDPClientPool.WriteAddrSeq(this.ep, this.taskID, NetConfigAddr.BOARD_MAC, macAddress, this.timeout);
 | 
			
		||||
        if (!ret.IsSuccessful)
 | 
			
		||||
@@ -262,13 +273,13 @@ public class NetConfig
 | 
			
		||||
    {
 | 
			
		||||
        // 清除UDP服务器接收缓冲区
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.HOST_IP, this.timeout);
 | 
			
		||||
        if (!ret.IsSuccessful)
 | 
			
		||||
@@ -296,13 +307,13 @@ public class NetConfig
 | 
			
		||||
    {
 | 
			
		||||
        // 清除UDP服务器接收缓冲区
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.BOARD_IP, this.timeout);
 | 
			
		||||
        if (!ret.IsSuccessful)
 | 
			
		||||
@@ -332,11 +343,11 @@ public class NetConfig
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.HOST_MAC, this.timeout);
 | 
			
		||||
        if (!ret.IsSuccessful)
 | 
			
		||||
@@ -364,13 +375,13 @@ public class NetConfig
 | 
			
		||||
    {
 | 
			
		||||
        // 清除UDP服务器接收缓冲区
 | 
			
		||||
        MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        // 刷新ARP
 | 
			
		||||
        var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        if (!refrshRet)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        }
 | 
			
		||||
        // var refrshRet = await Arp.UpdateArpEntryByPingAsync(this.address);
 | 
			
		||||
        // if (!refrshRet)
 | 
			
		||||
        // {
 | 
			
		||||
        //     logger.Warn($"Refrash Arp failed, but maybe not a big deal.");
 | 
			
		||||
        // }
 | 
			
		||||
 | 
			
		||||
        var ret = await UDPClientPool.ReadAddrSeq(this.ep, this.taskID, NetConfigAddr.BOARD_MAC, this.timeout);
 | 
			
		||||
        if (!ret.IsSuccessful)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										118
									
								
								src/APIClient.ts
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								src/APIClient.ts
									
									
									
									
									
								
							@@ -1278,6 +1278,124 @@ export class DataClient {
 | 
			
		||||
        }
 | 
			
		||||
        return Promise.resolve<Board[]>(null as any);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新板卡名称(管理员权限)
 | 
			
		||||
     * @param boardId (optional) 
 | 
			
		||||
     * @param newName (optional) 
 | 
			
		||||
     */
 | 
			
		||||
    updateBoardName(boardId: string | undefined, newName: string | undefined): Promise<number> {
 | 
			
		||||
        let url_ = this.baseUrl + "/api/Data/UpdateBoardName?";
 | 
			
		||||
        if (boardId === null)
 | 
			
		||||
            throw new Error("The parameter 'boardId' cannot be null.");
 | 
			
		||||
        else if (boardId !== undefined)
 | 
			
		||||
            url_ += "boardId=" + encodeURIComponent("" + boardId) + "&";
 | 
			
		||||
        if (newName === null)
 | 
			
		||||
            throw new Error("The parameter 'newName' cannot be null.");
 | 
			
		||||
        else if (newName !== undefined)
 | 
			
		||||
            url_ += "newName=" + encodeURIComponent("" + newName) + "&";
 | 
			
		||||
        url_ = url_.replace(/[?&]$/, "");
 | 
			
		||||
 | 
			
		||||
        let options_: RequestInit = {
 | 
			
		||||
            method: "POST",
 | 
			
		||||
            headers: {
 | 
			
		||||
                "Accept": "application/json"
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return this.http.fetch(url_, options_).then((_response: Response) => {
 | 
			
		||||
            return this.processUpdateBoardName(_response);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected processUpdateBoardName(response: Response): Promise<number> {
 | 
			
		||||
        const status = response.status;
 | 
			
		||||
        let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
 | 
			
		||||
        if (status === 200) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            let result200: any = null;
 | 
			
		||||
            let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
 | 
			
		||||
                result200 = resultData200 !== undefined ? resultData200 : <any>null;
 | 
			
		||||
    
 | 
			
		||||
            return result200;
 | 
			
		||||
            });
 | 
			
		||||
        } else if (status === 400) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            let result400: any = null;
 | 
			
		||||
            let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
 | 
			
		||||
            result400 = ProblemDetails.fromJS(resultData400);
 | 
			
		||||
            return throwException("A server side error occurred.", status, _responseText, _headers, result400);
 | 
			
		||||
            });
 | 
			
		||||
        } else if (status === 500) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            return throwException("A server side error occurred.", status, _responseText, _headers);
 | 
			
		||||
            });
 | 
			
		||||
        } else if (status !== 200 && status !== 204) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            return throwException("An unexpected server error occurred.", status, _responseText, _headers);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        return Promise.resolve<number>(null as any);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 更新板卡状态(管理员权限)
 | 
			
		||||
     * @param boardId (optional) 
 | 
			
		||||
     * @param newStatus (optional) 
 | 
			
		||||
     */
 | 
			
		||||
    updateBoardStatus(boardId: string | undefined, newStatus: BoardStatus | undefined): Promise<number> {
 | 
			
		||||
        let url_ = this.baseUrl + "/api/Data/UpdateBoardStatus?";
 | 
			
		||||
        if (boardId === null)
 | 
			
		||||
            throw new Error("The parameter 'boardId' cannot be null.");
 | 
			
		||||
        else if (boardId !== undefined)
 | 
			
		||||
            url_ += "boardId=" + encodeURIComponent("" + boardId) + "&";
 | 
			
		||||
        if (newStatus === null)
 | 
			
		||||
            throw new Error("The parameter 'newStatus' cannot be null.");
 | 
			
		||||
        else if (newStatus !== undefined)
 | 
			
		||||
            url_ += "newStatus=" + encodeURIComponent("" + newStatus) + "&";
 | 
			
		||||
        url_ = url_.replace(/[?&]$/, "");
 | 
			
		||||
 | 
			
		||||
        let options_: RequestInit = {
 | 
			
		||||
            method: "POST",
 | 
			
		||||
            headers: {
 | 
			
		||||
                "Accept": "application/json"
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return this.http.fetch(url_, options_).then((_response: Response) => {
 | 
			
		||||
            return this.processUpdateBoardStatus(_response);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected processUpdateBoardStatus(response: Response): Promise<number> {
 | 
			
		||||
        const status = response.status;
 | 
			
		||||
        let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
 | 
			
		||||
        if (status === 200) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            let result200: any = null;
 | 
			
		||||
            let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
 | 
			
		||||
                result200 = resultData200 !== undefined ? resultData200 : <any>null;
 | 
			
		||||
    
 | 
			
		||||
            return result200;
 | 
			
		||||
            });
 | 
			
		||||
        } else if (status === 400) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            let result400: any = null;
 | 
			
		||||
            let resultData400 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
 | 
			
		||||
            result400 = ProblemDetails.fromJS(resultData400);
 | 
			
		||||
            return throwException("A server side error occurred.", status, _responseText, _headers, result400);
 | 
			
		||||
            });
 | 
			
		||||
        } else if (status === 500) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            return throwException("A server side error occurred.", status, _responseText, _headers);
 | 
			
		||||
            });
 | 
			
		||||
        } else if (status !== 200 && status !== 204) {
 | 
			
		||||
            return response.text().then((_responseText) => {
 | 
			
		||||
            return throwException("An unexpected server error occurred.", status, _responseText, _headers);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        return Promise.resolve<number>(null as any);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class DDSClient {
 | 
			
		||||
 
 | 
			
		||||
@@ -134,21 +134,29 @@
 | 
			
		||||
          <h4 class="font-semibold">网络配置信息:</h4>
 | 
			
		||||
          <div class="bg-base-200 p-3 rounded">
 | 
			
		||||
            <div class="text-sm space-y-1">
 | 
			
		||||
              <div><span class="font-medium">主机IP:</span> {{ networkConfig.hostIP }}</div>
 | 
			
		||||
              <div><span class="font-medium">板卡IP:</span> {{ networkConfig.boardIP }}</div>
 | 
			
		||||
              <div><span class="font-medium">主机MAC:</span> {{ networkConfig.hostMAC }}</div>
 | 
			
		||||
              <div><span class="font-medium">板卡MAC:</span> {{ networkConfig.boardMAC }}</div>
 | 
			
		||||
              <div>
 | 
			
		||||
                <span class="font-medium">主机IP:</span>
 | 
			
		||||
                {{ networkConfig.hostIP }}
 | 
			
		||||
              </div>
 | 
			
		||||
              <div>
 | 
			
		||||
                <span class="font-medium">板卡IP:</span>
 | 
			
		||||
                {{ networkConfig.boardIP }}
 | 
			
		||||
              </div>
 | 
			
		||||
              <div>
 | 
			
		||||
                <span class="font-medium">主机MAC:</span>
 | 
			
		||||
                {{ networkConfig.hostMAC }}
 | 
			
		||||
              </div>
 | 
			
		||||
              <div>
 | 
			
		||||
                <span class="font-medium">板卡MAC:</span>
 | 
			
		||||
                {{ networkConfig.boardMAC }}
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <!-- 操作按钮 -->
 | 
			
		||||
        <div class="modal-action">
 | 
			
		||||
          <button
 | 
			
		||||
            type="button"
 | 
			
		||||
            class="btn btn-primary"
 | 
			
		||||
            @click="handleSuccess"
 | 
			
		||||
          >
 | 
			
		||||
          <button type="button" class="btn btn-primary" @click="handleSuccess">
 | 
			
		||||
            确认
 | 
			
		||||
          </button>
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -166,7 +174,9 @@
 | 
			
		||||
import { ref, reactive, watch } from "vue";
 | 
			
		||||
import { AuthManager } from "../../utils/AuthManager";
 | 
			
		||||
import { useAlertStore } from "../../components/Alert";
 | 
			
		||||
import type { NetworkConfigDto } from "../../APIClient";
 | 
			
		||||
import { BoardStatus, type NetworkConfigDto } from "../../APIClient";
 | 
			
		||||
import { useRequiredInjection } from "@/utils/Common";
 | 
			
		||||
import { useBoardManager } from "@/utils/BoardManager";
 | 
			
		||||
 | 
			
		||||
// Props 和 Emits
 | 
			
		||||
interface Props {
 | 
			
		||||
@@ -184,8 +194,12 @@ const emit = defineEmits<Emits>();
 | 
			
		||||
// 使用 Alert
 | 
			
		||||
const alertStore = useAlertStore();
 | 
			
		||||
 | 
			
		||||
const boardManager = useRequiredInjection(useBoardManager);
 | 
			
		||||
 | 
			
		||||
// 当前步骤
 | 
			
		||||
const currentStep = ref<'input' | 'pairing' | 'configuring' | 'result'>('input');
 | 
			
		||||
const currentStep = ref<"input" | "pairing" | "configuring" | "result">(
 | 
			
		||||
  "input",
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
// 表单数据
 | 
			
		||||
const form = reactive({
 | 
			
		||||
@@ -231,7 +245,7 @@ function validateForm(): boolean {
 | 
			
		||||
function resetForm() {
 | 
			
		||||
  form.name = "Board1";
 | 
			
		||||
  errors.name = "";
 | 
			
		||||
  currentStep.value = 'input';
 | 
			
		||||
  currentStep.value = "input";
 | 
			
		||||
  addedBoardId.value = "";
 | 
			
		||||
  networkConfig.value = null;
 | 
			
		||||
}
 | 
			
		||||
@@ -255,13 +269,13 @@ async function handleSubmit() {
 | 
			
		||||
  try {
 | 
			
		||||
    // 通过 AuthManager 获取认证的 DataClient
 | 
			
		||||
    const dataClient = AuthManager.createAuthenticatedDataClient();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // 添加板卡到数据库
 | 
			
		||||
    const boardId = await dataClient.addBoard(form.name.trim());
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    if (boardId) {
 | 
			
		||||
      addedBoardId.value = boardId;
 | 
			
		||||
      currentStep.value = 'pairing';
 | 
			
		||||
      currentStep.value = "pairing";
 | 
			
		||||
      alertStore?.success("板卡添加成功,请开启配对模式");
 | 
			
		||||
    } else {
 | 
			
		||||
      alertStore?.error("板卡添加失败");
 | 
			
		||||
@@ -281,10 +295,10 @@ async function handleCancelPairing() {
 | 
			
		||||
  try {
 | 
			
		||||
    // 通过 AuthManager 获取认证的 DataClient
 | 
			
		||||
    const dataClient = AuthManager.createAuthenticatedDataClient();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // 删除添加的板卡
 | 
			
		||||
    await dataClient.deleteBoard(addedBoardId.value);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    alertStore?.info("已取消添加实验板");
 | 
			
		||||
    emit("update:visible", false);
 | 
			
		||||
    resetForm();
 | 
			
		||||
@@ -299,7 +313,7 @@ async function handlePairingConfirm() {
 | 
			
		||||
  if (!addedBoardId.value) return;
 | 
			
		||||
 | 
			
		||||
  isConfiguring.value = true;
 | 
			
		||||
  currentStep.value = 'configuring';
 | 
			
		||||
  currentStep.value = "configuring";
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    // 通过 AuthManager 获取认证的客户端
 | 
			
		||||
@@ -308,7 +322,7 @@ async function handlePairingConfirm() {
 | 
			
		||||
 | 
			
		||||
    // 获取数据库中对应分配的板卡信息
 | 
			
		||||
    const boardInfo = await dataClient.getBoardByID(addedBoardId.value);
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    if (!boardInfo) {
 | 
			
		||||
      throw new Error("无法获取板卡信息");
 | 
			
		||||
    }
 | 
			
		||||
@@ -321,21 +335,34 @@ async function handlePairingConfirm() {
 | 
			
		||||
    await netConfigClient.setBoardIP(boardInfo.ipAddr);
 | 
			
		||||
    await netConfigClient.setBoardMAC(boardInfo.macAddr);
 | 
			
		||||
 | 
			
		||||
    // 更新板卡状态为可用
 | 
			
		||||
    if (
 | 
			
		||||
      (await dataClient.updateBoardStatus(
 | 
			
		||||
        boardInfo.id,
 | 
			
		||||
        BoardStatus.Available,
 | 
			
		||||
      )) != 1
 | 
			
		||||
    ) {
 | 
			
		||||
      throw new Error("无法更新板卡状态");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!(await boardManager.getAllBoards()).success) {
 | 
			
		||||
      alertStore?.error("无法获取板卡列表");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 获取实验板网络信息
 | 
			
		||||
    const networkInfo = await netConfigClient.getNetworkConfig();
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    if (networkInfo) {
 | 
			
		||||
      networkConfig.value = networkInfo;
 | 
			
		||||
      currentStep.value = 'result';
 | 
			
		||||
      currentStep.value = "result";
 | 
			
		||||
      alertStore?.success("实验板配置成功");
 | 
			
		||||
    } else {
 | 
			
		||||
      throw new Error("无法获取网络配置信息");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    console.error("配置实验板失败:", error);
 | 
			
		||||
    alertStore?.error("配置实验板失败");
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // 配置失败,删除数据库中的板卡信息
 | 
			
		||||
    try {
 | 
			
		||||
      const dataClient = AuthManager.createAuthenticatedDataClient();
 | 
			
		||||
@@ -343,9 +370,9 @@ async function handlePairingConfirm() {
 | 
			
		||||
    } catch (deleteError) {
 | 
			
		||||
      console.error("删除板卡失败:", deleteError);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // 返回输入步骤
 | 
			
		||||
    currentStep.value = 'input';
 | 
			
		||||
    currentStep.value = "input";
 | 
			
		||||
  } finally {
 | 
			
		||||
    isConfiguring.value = false;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user