---
name: "useDevices"
mode: "api"
versionRequirements:
  - { name: "@ray-js/panel-sdk", version: "1.16.0" }
title: "useDevices"
summary: "多设备管理 useDevices Hook 说明，介绍如何读取多台关联设备的实例状态、网络状态和功能点模型，并通过 selector 优化渲染性能。"
---

## useDevices

> [VERSION] @ray-js/panel-sdk >= 1.16.0

> 💡 使用前需挂载 SdmDevicesProvider 并配置关联设备映射。在线状态 vs 网络状态（务必区分）：
> - 判断「某个设备是否在线」请用 devices.main?.devInfo?.isOnline（设备云端/本地综合在线情况）。
> - devices.main?.network 反映的是「当前手机的网络环境」（所有设备共享），其中 isConnected 表示手机是否联网、networkType 为网络类型；它不包含设备在线信息，也没有 isOnline 字段。性能优化（最佳实践）：
> 1. 始终使用 selector 精确挑选数据，例如 useDevices(devices => devices.main?.network)，确保仅当依赖数据改变时才触发组件重渲染。
> 2. 对于派生计算等复杂场景，可利用 equalityFn 自定义比对逻辑以阻断无效渲染。
> 3. 若希望 devicesData.lamp1、devicesData.lamp2 等获得完整 DP 类型推导，请参考 [多设备管理 - 常见问题](/cn/miniapp/solution-panel/ability/common/multi-device/faq)。

### 描述

获取关联设备实例列表的状态集合数据。 不传 selector 时返回完整设备数据集合，任一设备的任何状态变化都会触发重渲染。强烈推荐始终传入 selector 仅选取所需属性，或提供自定义 equalityFn，以优化渲染性能并避免无效渲染。

### 参数

`Params`

| 参数 | 类型 | 必填 | 描述 |
| --- | --- | --- | --- |
| `selector` | `(devicesData: { [key: string]: DeviceData }) => any;` | 否 | 选择器函数，入参为所有关联设备的状态集合对象。   key 为设备标识，value 包含 devInfo、dpSchema、network、bluetooth 四个属性 |
| `equalityFn` | `(prev: any, next: any) => boolean;` | 否 | 自定义比较函数，返回 true 则不触发重渲染，默认 shallow equal |

### 返回值

类型: `any`

匹配选择器的设备状态数据，类型由 selector 返回值自动推导

### 引用对象

##### `type` DeviceData

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `devInfo` | `DevInfo` | 设备信息（含 codeIds / idCodes 进行功能点 Code ↔ ID 互查） |
| `dpSchema` | `DpSchema` | 功能点模型集合（key 为 dpCode） |
| `network` | `NetworkState` | 当前手机的网络连接状态（所有设备共享，非设备在线状态；设备是否在线见 devInfo.isOnline） |
| `bluetooth` | `{ available: boolean; }` | 蓝牙适配器状态 |

##### `type` DevInfo

设备信息

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `idCodes` | `Record<string, string>` | dp id 与 dp code 的映射 |
| `codeIds` | `Record<string, string>` | dp code 与 dp id 的映射 |
| `capability` | `Capability` | 产品通讯能力标位，按二进制位运算的方式进行判断计算，如 Wi-Fi、Bluetooth、ZigBee、SigMesh 等  - Wi-Fi (bit 0, 十进制值: 1): wifi无线 - Cable (bit 1, 十进制值: 2): 有线 - GPRS (bit 2, 十进制值: 4): 类似2g网络 - NB-IoT (bit 3, 十进制值: 6): 物联网卡网络 - Bluetooth (bit 10, 十进制值: 1024): 蓝牙单点 - BLEMesh (bit 11, 十进制值: 2048): 蓝牙私有mesh - ZigBee (bit 12, 十进制值: 4096): 2.4g频段 - Infrared (bit 13, 十进制值: 8192): 红外 - 433 (subpieces) (bit 14, 十进制值: 16384): 433mhz - SigMesh (bit 15, 十进制值: 32768): 蓝牙标准Mesh - MCU (bit 16, 十进制值: 65536): mcu - SMesh (bit 17, 十进制值: 131072): 类似ZigBee - Cat1 (bit 20, 十进制值: 1048576): 通常使用3g网络 - Beacon (bit 21, 十进制值: 2097152): 蓝牙Beacon - Thread (bit 25, 十进制值: 33554432): Thread能力 |
| `devAttribute` | `DevAttribute` | 设备能力标位，由固件上报 位数含义: - 第 1 位 (bit 0): 设备是否支持免配网 - 第 2 位 (bit 1): 设备支持 dp query 31 号协议查询 - 第 3 位 (bit 2): 设备是否具有本地联动能力 - 第 4 位 (bit 3): 设备是否支持 WIFI 扫描 - 第 5 位 (bit 4): 设备是否支持 Google Local Home - 第 6 位 (bit 5): 设备是否支持闪电配网能力 - 第 7 位 (bit 6): 设备是否支持蓝牙控制 - 第 8 位 (bit 7): 设备是否支持安防能力 - 第 9 位 (bit 8): 设备是否是共享设备 - 第 10 位 (bit 9): 设备是否支持日出日落定时 - 第 11 位 (bit 10): 设备是否支持故障替换能力 - 第 12 位 (bit 11): 设备是否支持 OTA - 第 13 位 (bit 12): 设备是否支持 WIFI 备用切换 - 第 15 位 (bit 14): 设备支持涂鸦标准协议 - 第 16 位 (bit 15): 设备支持自定义透传 - 第 17 位 (bit 16): 设备是否支持行业能力 |
| `schema` | `DpSchema[]` | 产品信息，schema，功能定义都在里面 |
| `panelConfig` | `PanelConfig` | 面板云配置 |

##### `interface` DpSchema

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `attr` | `number` | 功能点属性标位，用于扩展功能点的附加能力标识 |
| `canTrigger` | `boolean` | 是否可作为自动化触发条件 |
| `code` | `string` | 功能点标识码，如 switch |
| `defaultRecommend` | `boolean` | 是否为默认推荐的功能点 |
| `editPermission` | `boolean` | 是否具有编辑权限 |
| `executable` | `boolean` | 是否可执行下发 |
| `extContent` | `string` | 功能点扩展内容，通常为 JSON 字符串 |
| `iconname` | `string` | 功能点图标名称 |
| `id` | `string \| number` | 功能点 ID |
| `mode` | `"rw" \| "ro" \| "wr"` | 功能点模式类型 rw: 可下发可上报（可读可写） ro: 只可上报（仅可读） wr: 只可下发（仅可写） |
| `name` | `string` | 功能点名称，一般用于语音等场景 |
| `property` | `Object` | 功能点属性 |
| `type` | `"raw" \| "obj"` | 功能点数据类型大类：raw 为原始字节流，obj 为结构化对象 |

##### `interface` NetworkState

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `isConnected` | `boolean` | 是否已连接 |
| `networkType` | `string` | 网络类型: WIFI \| 5G \| 4G \| 3G \| 2G \| GPRS \| UNKNOWN \| NONE |
| `signalStrength` | `number` | 信号强弱，单位 dbm |

##### `type` GetSmartDeviceModelDevInfo

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `dpCodes` | `object` |  |
| `dps` | `object` |  |
| `idCodes` | `object` |  |
| `codeIds` | `object` |  |
| `schema` | `S` |  |

##### `type` Capability

产品通讯能力标位，按二进制位运算的方式进行判断计算，如 Wi-Fi、Bluetooth、ZigBee、SigMesh 等

- Wi-Fi (bit 0, 十进制值: 1): wifi无线
- Cable (bit 1, 十进制值: 2): 有线
- GPRS (bit 2, 十进制值: 4): 类似2g网络
- NB-IoT (bit 3, 十进制值: 6): 物联网卡网络
- Bluetooth (bit 10, 十进制值: 1024): 蓝牙单点
- BLEMesh (bit 11, 十进制值: 2048): 蓝牙私有mesh
- ZigBee (bit 12, 十进制值: 4096): 2.4g频段
- Infrared (bit 13, 十进制值: 8192): 红外
- 433 (subpieces) (bit 14, 十进制值: 16384): 433mhz
- SigMesh (bit 15, 十进制值: 32768): 蓝牙标准Mesh
- MCU (bit 16, 十进制值: 65536): mcu
- SMesh (bit 17, 十进制值: 131072): 类似ZigBee
- Cat1 (bit 20, 十进制值: 1048576): 通常使用3g网络
- Beacon (bit 21, 十进制值: 2097152): 蓝牙Beacon
- Thread (bit 25, 十进制值: 33554432): Thread能力

```typescript
export type Capability = number;
```

##### `type` DevAttribute

设备能力标位，由固件上报

位数含义:
- 第 1 位 (bit 0): 设备是否支持免配网
- 第 2 位 (bit 1): 设备支持 dp query 31 号协议查询
- 第 3 位 (bit 2): 设备是否具有本地联动能力
- 第 4 位 (bit 3): 设备是否支持 WIFI 扫描
- 第 5 位 (bit 4): 设备是否支持 Google Local Home
- 第 6 位 (bit 5): 设备是否支持闪电配网能力
- 第 7 位 (bit 6): 设备是否支持蓝牙控制
- 第 8 位 (bit 7): 设备是否支持安防能力
- 第 9 位 (bit 8): 设备是否是共享设备
- 第 10 位 (bit 9): 设备是否支持日出日落定时
- 第 11 位 (bit 10): 设备是否支持故障替换能力
- 第 12 位 (bit 11): 设备是否支持 OTA
- 第 13 位 (bit 12): 设备是否支持 WIFI 备用切换
- 第 15 位 (bit 14): 设备支持涂鸦标准协议
- 第 16 位 (bit 15): 设备支持自定义透传
- 第 17 位 (bit 16): 设备是否支持行业能力

```typescript
export type DevAttribute = number;
```

##### `interface` PanelConfig

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `bic` | `CloudConfig[]` | 云定时和跳转链接配置 |
| `fun` | `FunConfig` | 功能配置 |

##### `type` DpId

```typescript
type DpId = number;
```

##### `interface` JumpUrlConfig

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `code` | `"jump_url"` | 跳转链接配置代码 |
| `description` | `string` | 跳转链接配置描述 |
| `name` | `string` | 跳转链接配置名称 |
| `selected` | `boolean` | 跳转链接配置是否选中 |

##### `interface` TimerConfig

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `code` | `"timer"` | 云定时配置代码 |
| `description` | `string` | 云定时配置描述 |
| `name` | `string` | 云定时配置名称 |
| `selected` | `boolean` | 云定时配置是否选中 |

##### `interface` FunConfig

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `tyabirysr4` | `string` | 背景色，当前仅涂鸦官方小程序支持 |
| `tyabirysr4_app` | `"follow" \| "--app-B1"` | 背景色跟随策略，follow 代表跟随 App，否则代表要替换的 App 变量路径，当前仅涂鸦官方小程序支持 |
| `tyabis5d9w` | `string` | 主题色，当前仅涂鸦官方小程序支持 |
| `tyabis5d9w_app` | `"follow" \| "--app-M1"` | 主题色跟随策略，follow 代表跟随 App，否则代表要替换的 App 变量路径，当前仅涂鸦官方小程序支持 |

##### `interface` CloudConfig

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `jump_url` | `JumpUrlConfig` | 跳转链接配置 |
| `timer` | `TimerConfig` | 云定时配置 |

##### `type` DpSchema.property

| 属性 | 类型 | 描述 |
| --- | --- | --- |
| `type` | `"string" \| "bool" \| "value" \| "enum" \| "bitmap" \| "raw"` | 功能点类型 |
| `range` | `string[] \| string[]` | 枚举值范围，type = enum 时才存在 |
| `label` | `string[] \| string[]` | 故障型标签列表，type = bitmap 时才存在 |
| `maxlen` | `number` | 故障型最大长度，type = bitmap 时才存在 |
| `unit` | `string` | 数值型单位，type = value 时才存在 |
| `min` | `number` | 数值型最小值，type = value 时才存在 |
| `max` | `number` | 数值型最大值，type = value 时才存在 |
| `scale` | `number` | 数值型精度，type = value 时才存在 |
| `step` | `number` | 数值型步长，type = value 时才存在 |


### 示例代码

#### 获取指定设备的在线状态

```tsx
import { useDevices } from '@ray-js/panel-sdk';

function DeviceOnlineStatus() {
  // 设备是否在线取决于 devInfo.isOnline，仅当 main 设备在线状态变化时才重渲染
  const isOnline = useDevices(devices => devices.main?.devInfo?.isOnline);
  return <Text>设备在线: {isOnline ? '是' : '否'}</Text>;
}
```

#### 获取当前手机的网络状态

```tsx
import { useDevices } from '@ray-js/panel-sdk';

function PhoneNetworkStatus() {
  // network 反映的是当前手机的网络环境（所有设备共享），并非某个设备的在线状态
  const network = useDevices(devices => devices.main?.network);
  return (
    <Text>
      网络: {network?.networkType}（{network?.isConnected ? '已连接' : '未连接'}）
    </Text>
  );
}
```

#### 自定义 rerender 策略

```tsx
import { useDevices } from '@ray-js/panel-sdk';

function PhoneNetworkStatus() {
  // 仅当手机网络的连接状态发生实质变更时更新，networkType/信号强度的抖动不触发重渲染
  const network = useDevices(
    devices => devices.main?.network,
    (prev, next) => prev?.isConnected === next?.isConnected
  );
  return <Text>网络已连接: {network?.isConnected ? '是' : '否'}</Text>;
}
```

#### 获取所有设备的基础信息

```tsx
import { useDevices } from '@ray-js/panel-sdk';

function DeviceList() {
  const allDevices = useDevices();
  return (
    <View>
      {Object.entries(allDevices).map(([key, data]) => (
        <Text key={key}>{data.devInfo.name}</Text>
      ))}
    </View>
  );
}
```
