---
name: "SmartDevicesManager.add"
mode: "api"
versionRequirements:
  - { name: "@ray-js/panel-sdk", version: "1.16.0" }
title: "add"
---

## SmartDevicesManager.add

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

> 💡 Throws an error if the deviceId already exists

### Description

Add a single device instance and complete initialization. If init() has not been called, it will auto-init first for backward compatibility. Typically used to dynamically add one associated device; throws an error if the deviceId already exists.

### Parameters

`Params`

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `config` | `AddConfig` | Yes | Device config |

### Return Value

Type: `Promise<SmartDeviceModel>`

Initialized device instance

### Referenced Types

##### `type` AddConfig

| Property | Type | Description |
| --- | --- | --- |
| `key` | `string` | Unique key for the device instance in the manager |
| `deviceId` | `string` | Device ID |
| `interceptors` | `SmartDeviceModelInterceptors` | Interceptor configuration for the device instance; commonly used with dp-kit to implement structured DP conversion; optional, not configured by default |
| `logConfig` | `LogConfig` | Logging configuration for the device instance; optional, not configured by default |

##### `type` SmartDeviceModelInterceptors

SmartDeviceModel interceptor config type for combined use with dp-kit/matter-kit.

| Property | Type | Description |
| --- | --- | --- |
| `onInit` | `(instance: SmartDeviceModel) => void` | Callback triggered after the device model has finished initializing |
| `init` | `Object` | Device model initialization interceptor configuration |
| `request` | `Object` | Request interceptor configuration |
| `response` | `Object` | Response interceptor configuration |

##### `type` LogConfig

Logging configuration

| Property | Type | Description |
| --- | --- | --- |
| `level` | `"VERBOSE" \| "SUCCESS" \| "INFO" \| "WARN" \| "FATAL"` | Log output level, default INFO. To suppress the default printing of each DP send/report, set it to WARN or higher |

##### `type` InitDpStateInterceptor

```typescript
export type InitDpStateInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P = InitDpStateInterceptorParams
> = Interceptor<S, P, InitDpStateInterceptorParams>;
```

##### `type` InitDevInfoInterceptor

```typescript
export type InitDevInfoInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P = {
    devInfo: GetSmartDeviceModelDevInfo<any>;
    action: InitDevInfoInterceptorAction;
  }
> = Interceptor<
  S,
  P,
  {
    devInfo: GetSmartDeviceModelDevInfo<any>;
    action: InitDevInfoInterceptorAction;
  }
>;
```

##### `type` PublishDpsInterceptor

```typescript
export type PublishDpsInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P extends any[] = Parameters<typeof publishDps>
> = (
  context: Context<S>
) => (next: (...params: P) => any) => (...params: Parameters<typeof publishDps>) => any;
```

##### `type` OnDpDataChangeInterceptor

```typescript
export type OnDpDataChangeInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P = DpDataChangeParams
> = Interceptor<S, P, DpDataChangeParams>;
```

##### `type` OnDeviceOnlineStatusUpdateInterceptor

```typescript
export type OnDeviceOnlineStatusUpdateInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P = DeviceOnlineStatusUpdateParams
> = Interceptor<S, P, DeviceOnlineStatusUpdateParams>;
```

##### `type` OnDeviceInfoUpdatedInterceptor

```typescript
export type OnDeviceInfoUpdatedInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P = DeviceInfoUpdatedParams
> = Interceptor<S, P, DeviceInfoUpdatedParams>;
```

##### `type` OnNetworkStatusChangeInterceptor

```typescript
export type OnNetworkStatusChangeInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P = NetworkStatusChangeParams
> = Interceptor<S, P, NetworkStatusChangeParams>;
```

##### `type` OnBluetoothAdapterStateChangeInterceptor

```typescript
export type OnBluetoothAdapterStateChangeInterceptor<
  S extends ReadonlyDpSchemaList = any,
  P = BluetoothAdapterStatusChangeParams
> = Interceptor<S, P, BluetoothAdapterStatusChangeParams>;
```

##### `type` InitDpStateInterceptorParams

| Property | Type | Description |
| --- | --- | --- |
| `dpState` | `DpState` | Current device DP state |
| `newDpState` | `DpState` | New device DP state |
| `action` | `"init" \| "onDpDataChange" \| "onDeviceInfoUpdated" \| "dp-kit"` | Interceptor action |

##### `type` GetSmartDeviceModelDevInfo

| Property | Type | Description |
| --- | --- | --- |
| `dpCodes` | `object` |  |
| `dps` | `object` |  |
| `idCodes` | `object` |  |
| `codeIds` | `object` |  |
| `schema` | `S` |  |

##### `type` SmartDeviceModelAbility

Container type for SmartDeviceModel abilities, used only for generic constraints and internal composition.

```typescript
export type SmartDeviceModelAbility<A extends SmartDeviceAbility = SmartDeviceAbility> = {
  [abilityName: string]: A;
};
```

##### `type` DpState

Datapoint status object, where the key is the datapoint code and the value is the datapoint value.

```typescript
export type DpState = Record<string, DpValue>;
```

##### `type` PublishDpsOptions

Underlying option type of publishDps, reused by the SDK’s internal request chain.

| Property | Type | Description |
| --- | --- | --- |
| `devInfo` | `DevInfo` |  |

##### `type` DevInfo

Device information

| Property | Type | Description |
| --- | --- | --- |
| `idCodes` | `Record<string, string>` | Mapping of dp id to dp code |
| `codeIds` | `Record<string, string>` | Mapping of dp code to dp id |
| `capability` | `Capability` | Product communication capability bit flags, determined via bitwise operations, such as Wi‑Fi, Bluetooth, ZigBee, SigMesh, etc.  - Wi‑Fi (bit 0, decimal value: 1): Wi‑Fi - Cable (bit 1, decimal value: 2): Wired - GPRS (bit 2, decimal value: 4): similar to 2G networks - NB‑IoT (bit 3, decimal value: 6): IoT SIM network - Bluetooth (bit 10, decimal value: 1024): Bluetooth point‑to‑point - BLEMesh (bit 11, decimal value: 2048): proprietary Bluetooth mesh - ZigBee (bit 12, decimal value: 4096): 2.4 GHz band - Infrared (bit 13, decimal value: 8192): Infrared - 433 (subpieces) (bit 14, decimal value: 16384): 433 MHz - SigMesh (bit 15, decimal value: 32768): Bluetooth standard mesh - MCU (bit 16, decimal value: 65536): MCU - SMesh (bit 17, decimal value: 131072): similar to ZigBee - Cat1 (bit 20, decimal value: 1048576): usually uses 3G networks - Beacon (bit 21, decimal value: 2097152): Bluetooth Beacon - Thread (bit 25, decimal value: 33554432): Thread capability |
| `devAttribute` | `DevAttribute` | Device capability bit flags, reported by firmware Bit meanings: - Bit 0: Whether the device supports zero‑config networking - Bit 1: Device supports dp query protocol 31 - Bit 2: Whether the device has local automation capability - Bit 3: Whether the device supports Wi‑Fi scanning - Bit 4: Whether the device supports Google Local Home - Bit 5: Whether the device supports fast provisioning - Bit 6: Whether the device supports Bluetooth control - Bit 7: Whether the device supports security capability - Bit 8: Whether the device is a shared device - Bit 9: Whether the device supports sunrise/sunset scheduling - Bit 10: Whether the device supports fault replacement capability - Bit 11: Whether the device supports OTA - Bit 12: Whether the device supports Wi‑Fi backup switchover - Bit 14: Device supports the Tuya standard protocol - Bit 15: Device supports custom passthrough - Bit 16: Whether the device supports industry capabilities |
| `schema` | `DpSchema[]` | Product information, including schema and function definitions |
| `panelConfig` | `PanelConfig` | Panel cloud configuration |

##### `type` DpId

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

##### `type` DpValue

Datapoint value type, which can be boolean, number, or string.

```typescript
export type DpValue = boolean | number | string;
```

##### `type` SendDpOption

DP send options. Can be used as the global default configuration for createDpKit, and can also be overridden in a single publishDps/action call.
The global `sendDpOption` suits product-level defaults;
options passed for a single send are suitable for temporarily overriding throttling, debouncing, protocol parsing, or optimistic update strategies.
Note: requires the dp-kit interceptor.

| Property | Type | Since | Description |
| --- | --- | --- | --- |
| `immediate` | `boolean` | - | Whether to trigger a state update immediately; requires the dp-kit interceptor |
| `ignoreDpDataResponse` | `boolean \| IgnoreDpChangeInterceptorOptions` | `1.11.0` | Whether to ignore DP reports; default false |
| `synchronizeDevProperty` | `boolean \| DevPropInterceptorOptions` | `1.11.0` | Whether to sync dpData with cloud device properties; default false |
| `ordered` | `boolean` | - | Whether to send multiple DPs in the order of the object’s keys; requires the dp-kit interceptor; default false |
| `checkRepeat` | `boolean` | - | Whether to check for duplicate values and skip sending; requires the dp-kit interceptor; default false Compared with the current `dpState`; duplicates are detected and not sent |
| `delay` | `number` | - | Delayed send; requires the dp-kit interceptor; default 0, in ms |
| `throttle` | `number` | - | Send throttling (conflicts with debounce); requires the dp-kit interceptor; default 0, in ms |
| `debounce` | `number` | - | Send debounce (conflicts with throttle); requires the dp-kit interceptor; default 0, in ms |
| `protocols` | `Record<string, CustomRawDpMap>` | - | A per-call DP protocol converter; requires the dp-kit interceptor. The key is the dpCode and the value is a `{ parser, formatter }` object: - parser(dpValue: string) => any — parses the raw DP string into a structured object - formatter(parsedValue: any) => string — serializes the structured object into a DP string Affects only this invocation and does not override the global protocols configuration in createDpKit |

##### `type` Capability

Product communication capability bit flags, determined via bitwise operations, such as Wi-Fi, Bluetooth, ZigBee, SigMesh, etc.

- Wi-Fi (bit 0, decimal value: 1): Wi-Fi wireless
- Cable (bit 1, decimal value: 2): Wired
- GPRS (bit 2, decimal value: 4): 2G-like network
- NB-IoT (bit 3, decimal value: 6): IoT SIM network
- Bluetooth (bit 10, decimal value: 1024): Single-point Bluetooth
- BLEMesh (bit 11, decimal value: 2048): Proprietary Bluetooth mesh
- ZigBee (bit 12, decimal value: 4096): 2.4 GHz band
- Infrared (bit 13, decimal value: 8192): Infrared
- 433 (subpieces) (bit 14, decimal value: 16384): 433 MHz
- SigMesh (bit 15, decimal value: 32768): Standard Bluetooth Mesh
- MCU (bit 16, decimal value: 65536): MCU
- SMesh (bit 17, decimal value: 131072): Similar to ZigBee
- Cat1 (bit 20, decimal value: 1048576): usually uses 3G network
- Beacon (bit 21, decimal value: 2097152): Bluetooth Beacon
- Thread (bit 25, decimal value: 33554432): Thread capability

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

##### `type` DevAttribute

Device capability bitmask, reported by firmware

Bit meanings:
- Bit 1 (bit 0): Whether the device supports zero-configuration networking
- Bit 2 (bit 1): Device supports dp query protocol 31
- Bit 3 (bit 2): Whether the device has local linkage capability
- Bit 4 (bit 3): Whether the device supports Wi-Fi scanning
- Bit 5 (bit 4): Whether the device supports Google Local Home
- Bit 6 (bit 5): Whether the device supports fast provisioning (Lightning pairing)
- Bit 7 (bit 6): Whether the device supports Bluetooth control
- Bit 8 (bit 7): Whether the device supports security capabilities
- Bit 9 (bit 8): Whether the device is a shared device
- Bit 10 (bit 9): Whether the device supports sunrise/sunset scheduling
- Bit 11 (bit 10): Whether the device supports fault replacement capability
- Bit 12 (bit 11): Whether the device supports OTA
- Bit 13 (bit 12): Whether the device supports Wi-Fi backup switchover
- Bit 15 (bit 14): Device supports the Tuya standard protocol
- Bit 16 (bit 15): Device supports custom passthrough
- Bit 17 (bit 16): Whether the device supports industry capabilities

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

##### `interface` PanelConfig

| Property | Type | Description |
| --- | --- | --- |
| `bic` | `CloudConfig[]` | Cloud scheduling and navigation link configuration |
| `fun` | `FunConfig` | Feature configuration |

##### `interface` DpSchema

| Property | Type | Description |
| --- | --- | --- |
| `attr` | `number` | DP attribute flag bit, used to mark additional capabilities of the DP |
| `canTrigger` | `boolean` | Whether it can be used as an automation trigger condition |
| `code` | `string` | DP code, e.g., switch |
| `defaultRecommend` | `boolean` | Whether it is the default recommended DP |
| `editPermission` | `boolean` | Whether it has edit permission |
| `executable` | `boolean` | Whether it can be issued (sent downstream) |
| `extContent` | `string` | DP extension content, typically a JSON string |
| `iconname` | `string` | DP icon name |
| `id` | `string \| number` | DP ID |
| `mode` | `"rw" \| "ro" \| "wr"` | DP mode type rw: writable and reportable (read/write) ro: report-only (read-only) wr: write-only |
| `name` | `string` | DP name, typically used in voice scenarios |
| `property` | `Object` | DP attributes |
| `type` | `"raw" \| "obj"` | DP data type categories: raw for raw byte stream, obj for structured object |

##### `type` IgnoreDpChangeInterceptorOptions

Configuration option to ignore the DP data change interceptor

Used to configure the debounce mechanism for DP reporting events on the device panel, preventing immediate responses after panel operations from affecting user experience or business logic

| Property | Type | Description |
| --- | --- | --- |
| `whiteDpCodes` | `string[]` | DP whitelist; reports will not be ignored |
| `timeout` | `number` | Debounce timeout check, in milliseconds, default 5000 - The maximum time between sending a DP from the panel and receiving the DP reply; dpDataChange is triggered only if this is exceeded. - Used to debounce DP reporting events |
| `customRule` | `(dpState: DpState, lastSendTimestamp: number) => boolean` | Custom ignore rules > Highest priority; when configured, whiteDpCodes and timeout become ineffective |

##### `type` DevPropInterceptorOptions

| Property | Type | Description |
| --- | --- | --- |
| `blackDpCodes` | `string[]` | DP blacklist; will not be synchronized to the cloud |
| `defaultState` | `DpState` | Default device state on first entry; supports async initialization |
| `throttle` | `number` | Send throttling, in milliseconds, defaults to 0 If set to 0, throttling is disabled. |

##### `type` CustomRawDpMap

Custom DP protocol converter for transforming between raw DP strings and structured objects.
Suitable for composite DPs of type raw/string (e.g., a light's colour_data "00ff003e8"),
splitting a single string into multiple semantic fields (e.g., { hue, saturation, value }).

| Property | Type | Description |
| --- | --- | --- |
| `parser` | `(dpValue: string) => any` | Parse the raw DP string reported by the device into a structured object |
| `formatter` | `(parsedDpValue: any) => string` | Serialize the structured object into a DP string to be sent to the device |

##### `interface` JumpUrlConfig

| Property | Type | Description |
| --- | --- | --- |
| `code` | `"jump_url"` | Navigation link config code |
| `description` | `string` | Navigation link config description |
| `name` | `string` | Navigation link config name |
| `selected` | `boolean` | Whether the navigation link config is selected |

##### `interface` TimerConfig

| Property | Type | Description |
| --- | --- | --- |
| `code` | `"timer"` | Cloud schedule config code |
| `description` | `string` | Cloud schedule config description |
| `name` | `string` | Cloud schedule config name |
| `selected` | `boolean` | Whether the cloud schedule config is selected |

##### `interface` FunConfig

| Property | Type | Description |
| --- | --- | --- |
| `tyabirysr4` | `string` | Background color, currently supported only in the Tuya official mini program |
| `tyabirysr4_app` | `"follow" \| "--app-B1"` | Background color follow strategy: 'follow' means inherit from the App; otherwise, specify the App variable path to replace. Currently supported only in the Tuya official mini program |
| `tyabis5d9w` | `string` | Theme color, currently supported only in the Tuya official mini program |
| `tyabis5d9w_app` | `"follow" \| "--app-M1"` | Theme color follow strategy: 'follow' means inherit from the App; otherwise, specify the App variable path to replace. Currently supported only in the Tuya official mini program |

##### `interface` CloudConfig

| Property | Type | Description |
| --- | --- | --- |
| `jump_url` | `JumpUrlConfig` | Navigation link configuration |
| `timer` | `TimerConfig` | Cloud scheduling configuration |

##### `type` SmartDeviceModelInterceptors.init

| Property | Type | Description |
| --- | --- | --- |
| `initDpState` | `InitDpStateInterceptor[]` | DP state transformation interceptor, invoked at the following times: - When the model initializes (action: 'init') - When DP data changes (action: 'onDpDataChange' \| 'dp-kit') - When device information updates (action: 'onDeviceInfoUpdated') The interceptor receives the full dpState and the newDpState for this change, and returns the processed dpState |
| `initDevInfo` | `InitDevInfoInterceptor[]` | Device info transformation interceptor, invoked when: - when the model initializes (action: 'init') - when the device's online status changes (action: 'onDeviceOnlineStatusUpdate') - when device info is updated (action: 'onDeviceInfoUpdated') |

##### `type` SmartDeviceModelInterceptors.request

| Property | Type | Description |
| --- | --- | --- |
| `publishDps` | `PublishDpsInterceptor[]` | DP publish interceptor, invoked when: - publishing DP (action: 'publishDps') The interceptor receives the full dpState and the newDpState for this change, and returns the processed dpState |

##### `type` SmartDeviceModelInterceptors.response

| Property | Type | Description |
| --- | --- | --- |
| `onDpDataChange` | `OnDpDataChangeInterceptor[]` | DP data change interceptor, invoked when: - DP data changes (action: 'onDpDataChange') The interceptor receives the full dpState and the newDpState for this change, and returns the processed dpState |
| `onDeviceOnlineStatusUpdate` | `OnDeviceOnlineStatusUpdateInterceptor[]` | Device online status change interceptor, invoked when: - the device's online status changes (action: 'onDeviceOnlineStatusUpdate') The interceptor receives the full dpState and the newDpState for this change, and returns the processed dpState |
| `onDeviceInfoUpdated` | `OnDeviceInfoUpdatedInterceptor[]` | Device info update interceptor, invoked when: - device info is updated (action: 'onDeviceInfoUpdated') The interceptor receives the full dpState and the newDpState for this change, and returns the processed dpState |
| `onNetworkStatusChange` | `OnNetworkStatusChangeInterceptor[]` | Network status change interceptor, invoked when: - network status changes (action: 'onNetworkStatusChange') The interceptor receives the full dpState and the newDpState for this change, and returns the processed dpState |
| `onBluetoothAdapterStateChange` | `OnBluetoothAdapterStateChangeInterceptor[]` | Bluetooth status change interceptor, invoked when: - Bluetooth adapter status changes (action: 'onBluetoothAdapterStateChange') The interceptor receives the full dpState and the newDpState for this change, and returns the processed dpState |

##### `type` DpSchema.property

| Property | Type | Description |
| --- | --- | --- |
| `type` | `"string" \| "bool" \| "value" \| "enum" \| "bitmap" \| "raw"` | DP type |
| `range` | `string[] \| string[]` | Enum value range; present only when type = enum |
| `label` | `string[] \| string[]` | Fault label list; present only when type = bitmap |
| `maxlen` | `number` | Maximum length for fault bitmap; present only when type = bitmap |
| `unit` | `string` | Unit (type = value only) |
| `min` | `number` | Minimum value (type = value only) |
| `max` | `number` | Maximum value (type = value only) |
| `scale` | `number` | Precision (type = value only) |
| `step` | `number` | Step (type = value only) |


### Examples

#### Dynamically add a single device

```ts
import { SmartDevicesManager, createDpKit } from '@ray-js/panel-sdk';

const deviceManager = new SmartDevicesManager();
const dpKit = createDpKit({ protocols });

const lamp = await deviceManager.add({
  key: 'lamp1',
  deviceId: 'xxx_device_id',
  interceptors: dpKit.interceptors,
  logConfig: { level: 'VERBOSE' },
});

lamp.getDevInfo();
```
