feat: 使用netsh指令设置arp
This commit is contained in:
		@@ -84,7 +84,7 @@ public static class Arp
 | 
			
		||||
        {
 | 
			
		||||
            // 格式化 MAC 地址以适配不同操作系统
 | 
			
		||||
            string formattedMac = FormatMacAddress(macAddress);
 | 
			
		||||
            string command = GetArpAddCommand(ipAddress, formattedMac, interfaceName);
 | 
			
		||||
            string command = await GetArpAddCommandAsync(ipAddress, formattedMac, interfaceName);
 | 
			
		||||
            var result = await ExecuteCommandAsync(command);
 | 
			
		||||
            return result.IsSuccess;
 | 
			
		||||
        }
 | 
			
		||||
@@ -181,13 +181,20 @@ public static class Arp
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 获取 ARP 添加命令
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    private static string GetArpAddCommand(string ipAddress, string macAddress, string? interfaceName)
 | 
			
		||||
    private static async Task<string> GetArpAddCommandAsync(string ipAddress, string macAddress, string? interfaceName)
 | 
			
		||||
    {
 | 
			
		||||
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
 | 
			
		||||
        {
 | 
			
		||||
            return string.IsNullOrWhiteSpace(interfaceName)
 | 
			
		||||
                ? $"arp -s {ipAddress} {macAddress}"
 | 
			
		||||
                : $"arp -s {ipAddress} {macAddress} {interfaceName}";
 | 
			
		||||
            if (!string.IsNullOrWhiteSpace(interfaceName))
 | 
			
		||||
            {
 | 
			
		||||
                // 通过 arp -a 获取接口索引
 | 
			
		||||
                var interfaceIdx = await GetWindowsInterfaceIndexAsync(interfaceName);
 | 
			
		||||
                if (interfaceIdx.HasValue)
 | 
			
		||||
                {
 | 
			
		||||
                    return $"netsh -c i i add neighbors {interfaceIdx.Value} {ipAddress} {macAddress}";
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return $"arp -s {ipAddress} {macAddress}";
 | 
			
		||||
        }
 | 
			
		||||
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
 | 
			
		||||
        {
 | 
			
		||||
@@ -207,6 +214,54 @@ public static class Arp
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 获取 Windows 接口索引
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="interfaceIp">接口IP地址</param>
 | 
			
		||||
    /// <returns>接口索引(十进制),如果未找到则返回null</returns>
 | 
			
		||||
    private static async Task<int?> GetWindowsInterfaceIndexAsync(string interfaceIp)
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var result = await ExecuteCommandAsync("arp -a");
 | 
			
		||||
            if (!result.IsSuccess)
 | 
			
		||||
                return null;
 | 
			
		||||
 | 
			
		||||
            var lines = result.Output.Split('\n', StringSplitOptions.RemoveEmptyEntries);
 | 
			
		||||
            
 | 
			
		||||
            foreach (var line in lines)
 | 
			
		||||
            {
 | 
			
		||||
                // 匹配接口行格式: Interface: 172.6.1.5 --- 0xa
 | 
			
		||||
                var interfacePattern = @"Interface:\s+(\d+\.\d+\.\d+\.\d+)\s+---\s+(0x[a-fA-F0-9]+)";
 | 
			
		||||
                var match = Regex.Match(line, interfacePattern);
 | 
			
		||||
                
 | 
			
		||||
                if (match.Success && match.Groups[1].Value == interfaceIp)
 | 
			
		||||
                {
 | 
			
		||||
                    // 将十六进制索引转换为十进制
 | 
			
		||||
                    var hexIndex = match.Groups[2].Value;
 | 
			
		||||
                    // 去掉 "0x" 前缀
 | 
			
		||||
                    var hexValue = hexIndex.StartsWith("0x", StringComparison.OrdinalIgnoreCase) 
 | 
			
		||||
                        ? hexIndex.Substring(2) 
 | 
			
		||||
                        : hexIndex;
 | 
			
		||||
                    
 | 
			
		||||
                    if (int.TryParse(hexValue, System.Globalization.NumberStyles.HexNumber, null, out int decimalIndex))
 | 
			
		||||
                    {
 | 
			
		||||
                        logger.Debug($"找到接口 {interfaceIp} 的索引: {hexIndex} -> {decimalIndex}");
 | 
			
		||||
                        return decimalIndex;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            logger.Warn($"未找到接口 {interfaceIp} 的索引");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ex, $"获取接口 {interfaceIp} 索引失败");
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 获取 ARP 删除命令
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -478,7 +533,9 @@ public static class Arp
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 新增 ARP 记录
 | 
			
		||||
        return await AddArpEntryAsync(ipAddress, formattedMac, interfaceName);
 | 
			
		||||
        var ret = await AddArpEntryAsync(ipAddress, formattedMac, interfaceName);
 | 
			
		||||
        if(!ret) logger.Error($"添加 ARP 记录失败: {ipAddress} -> {formattedMac} on {interfaceName}");
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System.IdentityModel.Tokens.Jwt;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using Microsoft.AspNetCore.Authorization;
 | 
			
		||||
@@ -16,6 +17,8 @@ namespace server.Controllers;
 | 
			
		||||
public class DataController : ControllerBase
 | 
			
		||||
{
 | 
			
		||||
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
 | 
			
		||||
    // 固定的实验板IP,端口,MAC地址
 | 
			
		||||
    private const string BOARD_IP = "169.254.109.0";
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// [TODO:description]
 | 
			
		||||
@@ -48,6 +51,53 @@ public class DataController : ControllerBase
 | 
			
		||||
        public DateTime? BoardExpireTime { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
    /// 获取本机IP地址(优先选择与实验板同网段的IP)
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <returns>本机IP地址</returns>
 | 
			
		||||
    private IPAddress GetLocalIPAddress()
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray();
 | 
			
		||||
            
 | 
			
		||||
            // 优先选择与实验板IP前三段相同的IP
 | 
			
		||||
            var sameSegmentIP = System.Net.NetworkInformation.NetworkInterface
 | 
			
		||||
                .GetAllNetworkInterfaces()
 | 
			
		||||
                .Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
 | 
			
		||||
                              && nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
 | 
			
		||||
                .SelectMany(nic => nic.GetIPProperties().UnicastAddresses)
 | 
			
		||||
                .Where(addr => addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
 | 
			
		||||
                .Select(addr => addr.Address)
 | 
			
		||||
                .FirstOrDefault(addr =>
 | 
			
		||||
                {
 | 
			
		||||
                    var segments = addr.ToString().Split('.');
 | 
			
		||||
                    return segments.Length == 4 &&
 | 
			
		||||
                           segments[0] == boardIpSegments[0] &&
 | 
			
		||||
                           segments[1] == boardIpSegments[1] &&
 | 
			
		||||
                           segments[2] == boardIpSegments[2];
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            if (sameSegmentIP != null)
 | 
			
		||||
                return sameSegmentIP;
 | 
			
		||||
 | 
			
		||||
            // 如果没有找到同网段的IP,返回第一个可用的IP
 | 
			
		||||
            return System.Net.NetworkInformation.NetworkInterface
 | 
			
		||||
                .GetAllNetworkInterfaces()
 | 
			
		||||
                .Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
 | 
			
		||||
                              && nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
 | 
			
		||||
                .SelectMany(nic => nic.GetIPProperties().UnicastAddresses)
 | 
			
		||||
                .Where(addr => addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
 | 
			
		||||
                .Select(addr => addr.Address)
 | 
			
		||||
                .FirstOrDefault() ?? IPAddress.Loopback;
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ex, "获取本机IP地址失败");
 | 
			
		||||
            return IPAddress.Loopback;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 用户登录,获取 JWT 令牌
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -228,7 +278,7 @@ public class DataController : ControllerBase
 | 
			
		||||
                return NotFound("没有可用的实验板");
 | 
			
		||||
 | 
			
		||||
            var boardInfo = boardOpt.Value;
 | 
			
		||||
            if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr)))
 | 
			
		||||
            if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString())))
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"无法配置ARP,实验板可能会无法连接");
 | 
			
		||||
            }
 | 
			
		||||
@@ -296,7 +346,7 @@ public class DataController : ControllerBase
 | 
			
		||||
                return NotFound("未找到对应的实验板");
 | 
			
		||||
 | 
			
		||||
            var boardInfo = ret.Value.Value;
 | 
			
		||||
            if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr)))
 | 
			
		||||
            if (!(await Arp.CheckOrAddAsync(boardInfo.IpAddr, boardInfo.MacAddr, GetLocalIPAddress().ToString())))
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"无法配置ARP,实验板可能会无法连接");
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -119,46 +119,7 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
    /// <returns>网络接口名称</returns>
 | 
			
		||||
    private string GetLocalNetworkInterface()
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var boardIpSegments = BOARD_IP.Split('.').Take(3).ToArray();
 | 
			
		||||
            
 | 
			
		||||
            // 优先选择与实验板IP前三段相同的网络接口
 | 
			
		||||
            var sameSegmentInterface = System.Net.NetworkInformation.NetworkInterface
 | 
			
		||||
                .GetAllNetworkInterfaces()
 | 
			
		||||
                .Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
 | 
			
		||||
                              && nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
 | 
			
		||||
                .FirstOrDefault(nic =>
 | 
			
		||||
                {
 | 
			
		||||
                    var ipAddresses = nic.GetIPProperties().UnicastAddresses
 | 
			
		||||
                        .Where(addr => addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
 | 
			
		||||
                        .Select(addr => addr.Address);
 | 
			
		||||
                    
 | 
			
		||||
                    return ipAddresses.Any(addr =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var segments = addr.ToString().Split('.');
 | 
			
		||||
                        return segments.Length == 4 &&
 | 
			
		||||
                               segments[0] == boardIpSegments[0] &&
 | 
			
		||||
                               segments[1] == boardIpSegments[1] &&
 | 
			
		||||
                               segments[2] == boardIpSegments[2];
 | 
			
		||||
                    });
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            if (sameSegmentInterface != null)
 | 
			
		||||
                return sameSegmentInterface.Name;
 | 
			
		||||
 | 
			
		||||
            // 如果没有找到同网段的接口,返回第一个可用的接口
 | 
			
		||||
            return System.Net.NetworkInformation.NetworkInterface
 | 
			
		||||
                .GetAllNetworkInterfaces()
 | 
			
		||||
                .Where(nic => nic.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up
 | 
			
		||||
                              && nic.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)
 | 
			
		||||
                .FirstOrDefault()?.Name ?? "未知";
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ex, "获取本机网络接口名称失败");
 | 
			
		||||
            return "未知";
 | 
			
		||||
        }
 | 
			
		||||
        return GetLocalIPAddress().ToString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -484,6 +445,50 @@ public class NetConfigController : ControllerBase
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 设置板卡MAC地址
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="boardMac">板卡MAC地址(格式:AA:BB:CC:DD:EE:FF)</param>
 | 
			
		||||
    /// <returns>操作结果</returns>
 | 
			
		||||
    [HttpPost("SetBoardMAC")]
 | 
			
		||||
    [EnableCors("Users")]
 | 
			
		||||
    [ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
 | 
			
		||||
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 | 
			
		||||
    public async Task<IActionResult> SetBoardMAC(string boardMac)
 | 
			
		||||
    {
 | 
			
		||||
        if (string.IsNullOrWhiteSpace(boardMac))
 | 
			
		||||
            return BadRequest("板卡MAC地址不能为空");
 | 
			
		||||
 | 
			
		||||
        // 解析MAC地址
 | 
			
		||||
        if (!TryParseMacAddress(boardMac, out var macBytes))
 | 
			
		||||
            return BadRequest("MAC地址格式不正确,请使用格式:AA:BB:CC:DD:EE:FF");
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            if (!(await InitializeArpAsync()))
 | 
			
		||||
            {
 | 
			
		||||
                throw new Exception("无法配置ARP记录");
 | 
			
		||||
            }
 | 
			
		||||
            // 创建网络配置客户端
 | 
			
		||||
            var netConfig = new NetConfig(BOARD_IP, BOARD_PORT, 0);
 | 
			
		||||
            var result = await netConfig.SetBoardMAC(macBytes);
 | 
			
		||||
 | 
			
		||||
            if (!result.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"设置板卡MAC地址失败: {result.Error}");
 | 
			
		||||
                return StatusCode(StatusCodes.Status500InternalServerError, $"设置失败: {result.Error}");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return Ok(result.Value);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ex, "设置板卡MAC地址时发生异常");
 | 
			
		||||
            return StatusCode(StatusCodes.Status500InternalServerError, "设置失败,请稍后重试");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 设置主机MAC地址
 | 
			
		||||
    /// </summary>
 | 
			
		||||
 
 | 
			
		||||
@@ -8,11 +8,11 @@ static class CameraAddr
 | 
			
		||||
{
 | 
			
		||||
    public const UInt32 BASE = 0x7000_0000;
 | 
			
		||||
 | 
			
		||||
    public const UInt32 STORE_ADDR = BASE + 0x12;
 | 
			
		||||
    public const UInt32 STORE_NUM = BASE + 0x13;
 | 
			
		||||
    public const UInt32 EXPECTED_VH = BASE + 0x14;
 | 
			
		||||
    public const UInt32 CAPTURE_ON = BASE + 0x15;
 | 
			
		||||
    public const UInt32 CAMERA_POWER = BASE + 0x16; //[0]: rstn, 0 is reset. [8]: power down, 1 is down.
 | 
			
		||||
    public const UInt32 DMA0_START_WRITE_ADDR = BASE + 0x0C;
 | 
			
		||||
    public const UInt32 DMA0_END_WRITE_ADDR = BASE + 0x0D;
 | 
			
		||||
    public const UInt32 DMA0_CAPTURE_CTRL = BASE + 0x0E; //[0]: on, 1 is on. [8]: reset, 1 is reset.
 | 
			
		||||
    public const UInt32 EXPECTED_VH = BASE + 0x0F;
 | 
			
		||||
    public const UInt32 CAMERA_POWER = BASE + 0x10; //[0]: rstn, 0 is reset. [8]: power down, 1 is down.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Camera
 | 
			
		||||
@@ -156,7 +156,7 @@ class Camera
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<bool>> EnableHardwareTrans(bool isEnable)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.CAPTURE_ON, Convert.ToUInt32(isEnable));
 | 
			
		||||
        var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.DMA0_CAPTURE_CTRL, (isEnable ? 0x00000001u : 0x00000100u));
 | 
			
		||||
        if (!ret.IsSuccessful)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error($"Failed to write CAPTURE_ON to camera at {this.address}:{this.port}, error: {ret.Error}");
 | 
			
		||||
@@ -361,7 +361,7 @@ class Camera
 | 
			
		||||
 | 
			
		||||
        // 1. 配置UDP相关寄存器
 | 
			
		||||
        {
 | 
			
		||||
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.STORE_ADDR, FrameAddr);
 | 
			
		||||
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.DMA0_START_WRITE_ADDR, FrameAddr);
 | 
			
		||||
            if (!ret.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"Failed to write STORE_ADDR: {ret.Error}");
 | 
			
		||||
@@ -375,7 +375,7 @@ class Camera
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.STORE_NUM, frameLength);
 | 
			
		||||
            var ret = await UDPClientPool.WriteAddr(this.ep, this.taskID, CameraAddr.DMA0_END_WRITE_ADDR, FrameAddr + frameLength - 1);
 | 
			
		||||
            if (!ret.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"Failed to write STORE_NUM: {ret.Error}");
 | 
			
		||||
@@ -635,7 +635,7 @@ class Camera
 | 
			
		||||
    {
 | 
			
		||||
        var basicRegisters = new UInt16[][]
 | 
			
		||||
        {
 | 
			
		||||
            [0x3103, 0x03], // system clock from pad, bit[1]
 | 
			
		||||
            [0x3103, 0x03], // system clock from pad, bit[1] //02
 | 
			
		||||
            [0x3017, 0xff],
 | 
			
		||||
            [0x3018, 0xff],
 | 
			
		||||
            [0x3037, 0x13],
 | 
			
		||||
@@ -750,6 +750,7 @@ class Camera
 | 
			
		||||
            [0x3c04, 0x28],
 | 
			
		||||
            [0x3c05, 0x98],
 | 
			
		||||
            [0x3c06, 0x00],
 | 
			
		||||
            [0x3c07, 0x07],
 | 
			
		||||
            [0x3c08, 0x00],
 | 
			
		||||
            [0x3c09, 0x1c],
 | 
			
		||||
            [0x3c0a, 0x9c],
 | 
			
		||||
@@ -803,12 +804,12 @@ class Camera
 | 
			
		||||
    {
 | 
			
		||||
        var aecRegisters = new UInt16[][]
 | 
			
		||||
        {
 | 
			
		||||
            [0x3a0f, 0x30], // AEC控制;stable range in high
 | 
			
		||||
            [0x3a10, 0x28], // AEC控制;stable range in low
 | 
			
		||||
            [0x3a1b, 0x30], // AEC控制;stable range out high
 | 
			
		||||
            [0x3a1e, 0x26], // AEC控制;stable range out low
 | 
			
		||||
            [0x3a11, 0x60], // AEC控制; fast zone high
 | 
			
		||||
            [0x3a1f, 0x14], // AEC控制; fast zone low
 | 
			
		||||
            [0x3a0f, 0x30], // AEC控制;stable range in high     //78
 | 
			
		||||
            [0x3a10, 0x28], // AEC控制;stable range in low      //68
 | 
			
		||||
            [0x3a1b, 0x30], // AEC控制;stable range out high        //78
 | 
			
		||||
            [0x3a1e, 0x26], // AEC控制;stable range out low     //68
 | 
			
		||||
            [0x3a11, 0x60], // AEC控制; fast zone high      //D0
 | 
			
		||||
            [0x3a1f, 0x14], // AEC控制; fast zone low       //40
 | 
			
		||||
            [0x3b07, 0x0a]  // 帧曝光模式
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -952,7 +953,7 @@ class Camera
 | 
			
		||||
    {
 | 
			
		||||
        var timingRegisters = new UInt16[][]
 | 
			
		||||
        {
 | 
			
		||||
            [0x3035, 0x41], // 60fps
 | 
			
		||||
            [0x3035, 0x21], // 60fps
 | 
			
		||||
            [0x3036, PLL_MUX],// PLL倍频
 | 
			
		||||
            [0x3c07, 0x08],
 | 
			
		||||
            [0x3820, 0x41], // vflip
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div
 | 
			
		||||
    class="min-h-screen bg-base-100 container mx-auto p-6 space-y-6 flex flex-row"
 | 
			
		||||
    class="min-h-screen bg-base-100 container-md mx-auto p-6 space-y-6 flex flex-row"
 | 
			
		||||
  >
 | 
			
		||||
    <ul class="menu bg-base-200 w-56 gap-2 rounded-2xl p-5">
 | 
			
		||||
      <li id="1" @click="setActivePage">
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
      </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
    <div class="divider divider-horizontal h-full"></div>
 | 
			
		||||
    <div class="card bg-base-300 w-300 rounded-2xl p-7">
 | 
			
		||||
    <div class="card bg-base-300 flex-1 rounded-2xl p-7">
 | 
			
		||||
      <div v-if="activePage === 1">
 | 
			
		||||
        <UserInfo />
 | 
			
		||||
      </div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user