# 设备

Device 类代表一个单一的 Luxonis 硬件设备（OAK 相机或 RAE
机器人）。在我们所有的设备上都有一个强大的机器人视觉核心（[RVC](https://docs.luxonis.com/hardware/platform/rvc/rvc2.md#rvc2)）。RVC 针对 AI
推理、计算机视觉操作以及处理感官输入（例如立体深度、视频编码器等）进行了优化。

## 设备 API

Device 对象代表一个 OAK 设备。启动设备时，需要向其上传一个 [Pipeline](https://docs.luxonis.com/software/depthai-components/pipeline.md)，该 Pipeline 将在 VPU
上执行。在代码中创建设备时，固件会与 Pipeline 和其他资产（如神经网络 blob）一起上传。

```python
pipeline = depthai.Pipeline()

# 创建节点，配置它们并将它们链接在一起

# 连接设备并将管道上传到设备
with depthai.Device(pipeline) as device:
    # 打印设备的 MxID、USB 速度和可用相机
    print('MxId:',device.getDeviceInfo().getMxId())
    print('USB speed:',device.getUsbSpeed())
    print('Connected cameras:',device.getConnectedCameras())
```

## 连接到指定设备

如果您有 [多个设备](https://docs.luxonis.com/software/depthai/multi-device-setup.md) 并且只想连接到其中一个，或者您的 OAK PoE 相机位于子网之外，您可以指定要连接的设备（通过
MxID、IP 地址或 USB 端口名称）。

```python
# 指定 MXID、IP 地址或 USB 路径
device_info = depthai.DeviceInfo("14442C108144F1D000") # MXID
#device_info = depthai.DeviceInfo("192.168.1.44") # IP 地址
#device_info = depthai.DeviceInfo("3.3.3") # USB 端口名称
with depthai.Device(pipeline, device_info) as device:
    # ...
```

## 时钟

depthai 时钟 dai.Clock.now()（Python）或 dai::Clock::now()（C++）是一个单调时钟，用于 depthai 库中的时间戳。它派生自
[std::chrono::steady_clock](https://en.cppreference.com/w/cpp/chrono/steady_clock)，不受系统时间变化（例如 NTP 同步）的影响。

该方法返回自主机（PC）启动以来的 datetime.timedelta（Python）或 std::chrono::steady_clock::duration（C++）。它在调用设备
[消息](https://docs.luxonis.com/software/depthai-components/messages.md) 的 getTimestamp() 时使用，并指示消息在设备上创建的时间。

设备上还有一个单独的单调时钟，用于获取自设备（OAK）启动以来的时间，可以通过 getTimestampDevice() 调用。

### 主机时钟同步

当 depthai 库连接到设备时，它会自动将设备的时间戳同步到主机的时间戳。时间戳同步以大约 5 秒的间隔持续进行，并且可以通过 API 进行配置（如下面的示例脚本所示）。

对于 PoE 相机，设备时钟与主机时钟的同步精度在 500µs 以下；对于 USB 相机，在 1σ（标准差）范围内精度在 200µs 以下。

上图显示了设备时钟相对于主机时钟的精度。我们连接了 3 个设备（OAK PoE 相机），所有设备都使用 [FSYNC Y
型适配器](https://shop71313603.taobao.com/?spm=pc_detail.30350276.shop_block.dshopinfo.27a17dd635FNDA) 进行硬件同步。树莓派（主机）有一个中断引脚连接到 FSYNC
线，因此在每帧开始时发生中断，并记录主机时钟。然后我们将帧（同步的）时间戳与主机时间戳进行比较并计算标准差。对于上面的直方图，我们运行了大约 3 小时的测试。

下图显示了设备时钟和主机时钟之间的差异。该图显示了设备时钟和主机时钟随时间的变化。该图是上述相同测试的结果。

```python
# 配置主机时钟同步示例

import depthai as dai
from datetime import timedelta
# 配置管道
with dai.Device(pipeline) as device:
    # 第一个值：时间同步运行之间的间隔
    # 第二个值：每次运行的时间同步样本数，用于计算更准确的值
    # 第三个值：如果为 True，则部分时间同步请求将在随机间隔内执行，否则在固定间隔内执行
    device.setTimesync(timedelta(seconds=5), 10, True) # (这些是默认值)
```

## 设备队列

初始化设备后，您可以创建与管道中的
[XLinkIn](https://docs.luxonis.com/software/depthai-components/nodes/xlink_in.md)/[XLinkOut](https://docs.luxonis.com/software/depthai-components/nodes/xlink_out.md)
节点匹配的输入/输出队列。这些队列将位于主机计算机（RAM 中）上。

```py
pipeline = dai.Pipeline()

xout = pipeline.createXLinkOut()
xout.setStreamName("output_name")
# ...
xin = pipeline.createXLinkIn()
xin.setStreamName("input_name")
# ...
with dai.Device(pipeline) as device:

  outputQueue = device.getOutputQueue("output_name", maxSize=5, blocking=False)
  inputQueue = device.getInputQueue("input_name")

  outputQueue.get() # 从队列读取，阻塞直到有消息到达
  outputQueue.tryGet() # 从队列读取，如果没有消息则返回 None（不阻塞）
  if outputQueue.has(): # 检查队列中是否有任何消息
```

当您定义输出队列时，设备可以随时向队列推送新消息，而主机也可以随时读取队列。

### 输出队列设置

当主机非常快速地读取队列时（例如在 while True
循环内），无论队列大小如何，队列大部分时间都会保持空状态。但当我们增加主机端的处理（如额外处理、分析等）时，可能会发生设备向主机队列推送消息的速度快于主机读取速度的情况。此时队列中的消息数量将开始增加——而 maxSize 和 blocking
设置将决定队列在此情况下的行为。两种常见配置如下：

```py
with dai.Device(pipeline) as device:
  # 如果您只需要最新消息，而不关心之前的消息；
  # 当新消息到达主机时，如果旧消息仍留在队列中，它将覆盖最旧的（最早的）消息
  q1 = device.getOutputQueue(name="name1", maxSize=1, blocking=False)

  # 如果您关心每一条消息（例如 H264/5 编码视频；如果丢失一帧，会出现伪影）；
  # 如果队列已满，设备将等待主机从队列中读取一条消息
  q2 = device.getOutputQueue(name="name2", maxSize=30, blocking=True) # 也是默认值 (maxSize=30/blocking=True)
```

这里使用 maxSize=30 仅作为示例，实际上可以是任何 int16 数值。由于设备队列位于主机计算机上，内存（RAM）通常并不稀缺，因此 maxSize 的影响不会太大。但如果您使用小型单板计算机（如 RPI Zero，512MB
RAM）并流式传输大帧（例如未压缩的 4K 图像），并且将 maxSize 设置得过高（同时读取队列不够快），则可能会迅速耗尽内存。

#### 一些额外信息

 * 队列是线程安全的——可以从任何线程访问。
 * 队列的创建方式是每个队列拥有自己的线程，负责接收、序列化/反序列化以及转发消息（输入/输出队列同理）。
 * Device 对象并非完全线程安全。某些 RPC 调用（例如 getLogLevel、setLogLevel、getDdrMemoryUsage）在设置互斥锁后才会变得线程安全（目前可能存在竞争条件）。

## 看门狗

看门狗是 DepthAI 的 POE（以太网供电）设备运行中的关键组件。当 DepthAI 与 POE 设备断开连接时，看门狗机制首先响应，启动摄像头复位。复位后紧接着进行完整的系统重启，包括加载 DepthAI 引导加载程序和初始化整个网络堆栈。

看门狗过程对于使摄像头可重新连接是必需的，通常需要大约 10 秒，这意味着最快重新连接时间为 10 秒。

### 自定义看门狗超时时间

将环境变量 DEPTHAI_WATCHDOG_INITIAL_DELAY 和 DEPTHAI_BOOTUP_TIMEOUT 设置为所需的超时值（以毫秒为单位），如下所示：

#### Windows Powershell

```bash
$env:DEPTHAI_WATCHDOG_INITIAL_DELAY=<my_value>
$env:DEPTHAI_BOOTUP_TIMEOUT=<my_value>
python3 script.py
```

#### Linux/macOS

```bash
DEPTHAI_WATCHDOG_INITIAL_DELAY=<my_value> DEPTHAI_BOOTUP_TIMEOUT=<my_value> python3 script.py
```

#### Windows CMD

```bash
set DEPTHAI_WATCHDOG_INITIAL_DELAY=<my_value>
set DEPTHAI_BOOTUP_TIMEOUT=<my_value>
python3 script.py
```

或者，您也可以直接在代码中设置超时时间：

```python
pipeline = depthai.Pipeline()

# 创建 BoardConfig 对象
config = depthai.BoardConfig()

# 设置参数
config.watchdogInitialDelayMs = <my_value>
config.watchdogTimeoutMs = <my_value>

pipeline.setBoardConfig(config)
```

通过调整这些设置，您可以定制看门狗功能以更好地满足特定需求。

## 环境变量

The following table lists various environment variables used in the system, along with their descriptions:

| 环境变量 | 描述 |
| --- | --- |
| `DEPTHAI_LEVEL` | 设置日志详细程度，选项：'trace', 'debug', 'warn', 'error', 'off' |
| `XLINK_LEVEL` | 设置 XLink 库的日志详细程度，选项：'debug', 'info', 'warn', 'error', 'fatal', 'off' |
| `DEPTHAI_INSTALL_SIGNAL_HANDLER` | 设为 0 以禁用安装 Backward 信号处理程序（用于打印堆栈跟踪） |
| `DEPTHAI_WATCHDOG` | 设置设备看门狗超时时间。用于调试（`DEPTHAI_WATCHDOG=0`）可防止进程暂停期间设备重置。 |
| `DEPTHAI_WATCHDOG_INITIAL_DELAY` | 指定设备看门狗启动前的延迟时间。 |
| `DEPTHAI_SEARCH_TIMEOUT` | 指定阻塞函数中设备搜索的超时时间（毫秒）。 |
| `DEPTHAI_CONNECT_TIMEOUT` | 指定建立到指定设备连接的超时时间（毫秒）。 |
| `DEPTHAI_BOOTUP_TIMEOUT` | 等待设备在发送二进制文件后启动的超时时间（毫秒）。 |
| `DEPTHAI_PROTOCOL` | 将默认搜索限制为指定协议。选项：any, usb, tcpip。 |
| `DEPTHAI_DEVICE_MXID_LIST` | 将默认搜索限制为指定的 MXID。接受逗号分隔的 MXID 列表。列表过滤结果为“AND”而非“OR”方式。 |
| `DEPTHAI_DEVICE_ID_LIST` | MXID 列表的别名。列表过滤结果为“AND”而非“OR”方式。 |
| `DEPTHAI_DEVICE_NAME_LIST` | 将默认搜索限制为指定的名称。接受逗号分隔的名称列表。列表过滤结果为“AND”而非“OR”方式。 |
| `DEPTHAI_DEVICE_BINARY` | 覆盖设备固件二进制文件。主要用于内部调试。 |
| `DEPTHAI_BOOTLOADER_BINARY_USB` | 覆盖设备 USB 引导加载程序二进制文件。主要用于内部调试。 |
| `DEPTHAI_BOOTLOADER_BINARY_ETH` | 覆盖设备网络引导加载程序二进制文件。主要用于内部调试。 |
| `DEPTHAI_DISABLE_CRASHDUMP_COLLECTION` | 设为 1 时，禁用向 Luxonis 发送崩溃转储。默认情况下，崩溃转储、管道、操作系统和 depthai 版本信息会发送给 Luxonis 用于诊断。 |
| `DEPTHAI_ENABLE_ANALYTICS_COLLECTION` | 设为 1 时，分析数据（管道模式）会发送给 Luxonis，用于进一步改进库。 |

## 参考

### depthai.Device(depthai.DeviceBase)

Kind: Class

Represents the DepthAI device with the methods to interact with it. Implements
the host-side queues to connect with XLinkIn and XLinkOut nodes

#### depthai.Device.Config

Kind: Class

Device specific configuration

##### board: BoardConfig

Kind: Class Variable

##### logLevel: depthai.LogLevel|None

Kind: Class Variable

##### nonExclusiveMode: bool

Kind: Class Variable

##### outputLogLevel: depthai.LogLevel|None

Kind: Class Variable

##### version: OpenVINO.Version

Kind: Class Variable

##### __init__(self)

Kind: Method

#### __enter__(self) -> Device: Device

Kind: Method

#### __init__()

Kind: Method

#### getInputQueue()

Kind: Method

#### getInputQueueNames(self) -> list[str]: list[str]

Kind: Method

Get all available input queue names

Returns:
Vector of input queue names

#### getOutputQueue()

Kind: Method

#### getOutputQueueNames(self) -> list[str]: list[str]

Kind: Method

Get all available output queue names

Returns:
Vector of output queue names

#### getQueueEvent()

Kind: Method

#### getQueueEvents()

Kind: Method
