---
name: "useDevice"
mode: "api"
versionRequirements:
  - { name: "@ray-js/panel-sdk", version: "1.2.0" }
title: "useDevice - 基于 sdm 的实例实现，能够在智能设备信息、所处环境网络状态、蓝牙状态等变动时驱动组件重新渲染"
summary: "useDevice 是 @ray-js/panel-sdk 提供的 React Hook，基于 SDM 实例实现。通过 selector 函数可订阅设备信息（devInfo）、网络状态（network.isConnected）、蓝牙状态等数据，数据变动时自动驱动组件重新渲染。支持自定义 equalityFn 控制重渲染（内置 shallow equal）。可获取 dpSchema 功能点模型集合（key 为 dpCode）、通过 codeIds 由功能点 Code 查 ID、通过 idCodes 由 ID 查 Code。群组环境下返回 GroupInfo 而非 DeviceInfo，需兼容 groupId/devId、name/groupName、在线状态（deviceList.some vs isCloudOnline）等字段差异。使用前需挂载 SdmProvider。通过 useDevice 可以获取dp scheme。"
questions:
  - "如何获取设备信息？如何获取网络状态？"
  - "useDevice 的 selector 函数如何订阅 device.network.isConnected 网络连接状态？"
  - "useDevice 内置 shallow equal 浅比较，如何通过自定义 equalityFn 控制只在特定字段变化时重渲染？"
  - "device.dpSchema 返回的对象结构是什么（key 为 dpCode，value 包含 attr、mode、property 等）？"
  - "如何通过 useDevice 的 device.devInfo.codeIds 由功能点 Code 获取对应的功能点 ID？"
  - "device.devInfo.idCodes 与 device.devInfo.codeIds 分别用于什么方向的 Code/ID 互查？"
  - "群组环境下 useDevice 返回的是 GroupInfo 而非 DeviceInfo，哪些字段需要兼容处理（groupId/devId、name/groupName）？"
  - "群组环境下如何判断在线状态（deviceList.some(dev => dev.isOnline) vs isCloudOnline）？"
  - "使用 useDevice 前为什么必须先挂载 SdmProvider，public-sdm 示例项目在哪里获取？"
  - "useDevice 的 TypeScript 泛型签名中 ReadonlyDpSchemaList 和 DeviceData 分别代表什么？"
  - "useDevice 关联的底层 SDM API 有哪些（getDevInfo、getDpSchema、getNetwork、getBluetooth）？"
---

<div style={{ display: 'flex', gap: '8px', marginBottom: '16px' }}>
  <span style={{ backgroundColor: '#52c41a', color: 'white', padding: '2px 8px', borderRadius: '4px', fontSize: '12px' }}>单设备支持</span>
  <span style={{ backgroundColor: '#faad14', color: 'white', padding: '2px 8px', borderRadius: '4px', fontSize: '12px' }}>群组部分支持</span>
</div>

## useDevice

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

> 💡 基于 sdm 实例实现。必须在 SdmProvider 内部使用。
> 使用前请注意检查项目是否已挂载了 SdmProvider，项目接入可参考 [智能设备模型 - 使用](/cn/miniapp/solution-panel/ability/common/sdm/usage)，全新项目可直接基于 [public-sdm](https://github.com/Tuya-Community/tuya-ray-materials/tree/main/template/PublicSdmTemplate) 示例项目进行开发。在线状态 vs 网络状态（务必区分）：
> - 判断「设备是否在线」请用 device.devInfo.isOnline（设备云端/本地综合在线情况）。
> - device.network 反映的是「当前手机的网络环境」（所有设备共享），其中 isConnected 表示手机是否联网、networkType 为网络类型；它不包含设备在线信息，也没有 isOnline 字段。

### 描述

获取智能设备信息、功能点模型、网络状态、蓝牙状态，数据变动时驱动组件重新渲染。 不传 selector 时返回完整 DeviceData，任何字段变化都触发重渲染，推荐始终传入 selector 仅选取所需功能点以优化渲染性能。

### 参数

`Params`

| 参数 | 类型 | 必填 | 描述 |
| --- | --- | --- | --- |
| `selector` | `(device: DeviceData) => any;` | 否 | 选择器函数，入参为包含 devInfo、dpSchema、network、bluetooth 的设备数据对象，返回值类型由 selector 选择器决定，可能为任意值 |
| `equalityFn` | `(prevDeviceData: DeviceData, nextDeviceData: DeviceData) => boolean;` | 否 | 自定义比较函数，返回 true 则不触发重渲染 |

### 返回值

类型: `DeviceData`

返回值类型由 selector 选择器决定，可能为任意值

**`type` DeviceData**

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

### 引用对象

##### `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 { useDevice } from '@ray-js/panel-sdk';

function Home() {
  const { devInfo, network } = useDevice();
  return <Text>{devInfo.name} - 网络: {network.isConnected ? '已连接' : '断开'}</Text>;
}
```

#### 订阅网络状态

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

function Home() {
  const isConnected = useDevice(device => device.network.isConnected);
  return <Text>网络: {isConnected ? '已连接' : '断开'}</Text>;
}
```

#### 自定义 rerender

```tsx
// 仅网络连接变化时更新
const network = useDevice(
  device => device.network,
  (prev, next) => prev.isConnected === next.isConnected,
);
```

#### 获取功能点模型集合

```tsx
const dpSchema = useDevice(device => device.dpSchema);
// dpSchema: { switch_led: { code, property, type, mode, ... }, ... }
```

#### 通过 codeIds / idCodes 进行功能点 Code ↔ ID 互查

```tsx
const devInfo = useDevice(device => device.devInfo);
const dpId = devInfo.codeIds['switch_led'];   // code → id
const dpCode = devInfo.idCodes[1];             // id → code
```

#### 群组环境兼容

```tsx
// 群组下 devInfo 实际为 GroupInfo，部分字段需适配
import { useDevice } from '@ray-js/panel-sdk';
import { Text, getLaunchOptionsSync } from '@ray-js/ray';

function Home() {
  const isGroup = !!getLaunchOptionsSync()?.query?.groupId;
  const devInfo = useDevice(d => d.devInfo);

  const id = isGroup ? devInfo.groupId : devInfo.devId;
  const name = devInfo.name || (isGroup ? devInfo.groupName : '设备');
  const isOnline = isGroup
    ? devInfo.deviceList?.some(d => d.isOnline)
    : devInfo.isCloudOnline;

  return <Text>{name}({id}) - {isOnline ? '在线' : '离线'}</Text>;
}
```
