---
name: "createDpKit"
mode: "api"
versionRequirements:
  - { name: "@ray-js/panel-sdk", version: "1.7.0" }
title: "createDpKit - Create a dp-kit instance"
summary: "createDpKit is a function provided by @ray-js/panel-sdk for creating a dp-kit instance. Key capabilities include customizing parser/formatter through protocols, automatically parsing and formatting complex DP types such as colour_data into hue/saturation/value, sendDpOption support for throttle, debounce, delay, checkRepeat, and ordered command sending, immediate UI updates after command sending without waiting for reporting, ignoreDpDataResponse to ignore device reporting responses with whiteDpCodes, timeout, and customRule, synchronizeDevProperty to sync cloud DP status with blackDpCodes and defaultState, and onBeforeSendDp/onAfterSendDp hooks. Use it with useStructuredProps/useStructuredActions. typings/sdm.d.ts provides global TypeScript declarations."
---

## createDpKit

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

> 💡 Pass the interceptors returned by createDpKit into SmartDeviceModel constructor options,
> and when used with useStructuredProps / useStructuredActions, call init after device initialization.

### Description

Create a DP protocol suite that provides structured DP parsing, send interception, and enhancements such as throttling/debouncing

### Parameters

`Params`

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `option` | `CreateDpKitOptions` | No | dp-kit configuration options |

### Return Value

Type: `CreateDpKitResult`

dp-kit instance, including methods such as init, interceptors, and destroy

**`type` CreateDpKitResult**

| Property | Type | Description |
| --- | --- | --- |
| `init` | `(device: any) => void` | Initialize device state; when used with useStructuredProps, call after the device model has finished initializing. |
| `interceptors` | `Record<string, any>` | dp-kit default interceptor configuration |
| `onDeviceInfoUpdated` | `(ctx: any) => (next: (data: any) => any) => (data: any) => any` | dp-kit onDeviceInfoUpdated interceptor; can be used standalone if needed. |
| `onDpDataChange` | `(ctx: any) => (next: (data: any) => any) => (data: any) => any` | dp-kit onDpDataChange interceptor; can be used standalone if needed. |
| `publishDps` | `(ctx: any) => (next: (dpState: Record<string, any>, options?: SendDpOption) => any) => (dpState: Record<string, any>, options?: SendDpOption) => any` | dp-kit publishDps interceptor; can be used standalone if needed. |
| `destroy` | `() => void` | Destroy dp-kit and clean up resources such as flush timers and throttling/debouncing maps. Should be called when SmartDeviceModel is destroyed (e.g., in SdmProvider's useEffect cleanup). |

### Referenced Types

##### `type` CreateDpKitOptions

createDpKit configuration options that unify protocol parsing, global dispatch options, and pre/post hooks.

| Property | Type | Description |
| --- | --- | --- |
| `protocols` | `Record<string, CustomRawDpMap>` | DP protocol mapping table that decomposes composite string-type DPs (e.g., colour_data) into structured objects. Keys are dpCode; values are custom Transformers.  Implement parser/formatter: `{ colour_data: new ColourTransformer() }`  - parser(raw: string) => T — Parse the raw string reported by the device into a structured object - formatter(data: T) => string — Serialize the structured object into a string to send to the device  After registration, you can read/write structured data via useStructuredProps / useStructuredActions. |
| `sendDpOption` | `SendDpOption` | DP dispatch options |
| `onBeforeSendDp` | `(dpState: DpState) => any` | Pre-dispatch hook for DP |
| `onAfterSendDp` | `(dpState: DpState) => any` | Pre-dispatch hook for DP |

##### `type` CreateDpKitResult

The result of createDpKit, containing a set of interceptors that can be attached directly to SmartDeviceModel, plus the `init` / `destroy` lifecycle methods required to initialize structured DP state.

| Property | Type | Description |
| --- | --- | --- |
| `init` | `(device: any) => void` | Initialize device state; when used with useStructuredProps, call after the device model has finished initializing. |
| `interceptors` | `Record<string, any>` | dp-kit default interceptor configuration |
| `onDeviceInfoUpdated` | `(ctx: any) => (next: (data: any) => any) => (data: any) => any` | dp-kit onDeviceInfoUpdated interceptor; can be used standalone if needed. |
| `onDpDataChange` | `(ctx: any) => (next: (data: any) => any) => (data: any) => any` | dp-kit onDpDataChange interceptor; can be used standalone if needed. |
| `publishDps` | `(ctx: any) => (next: (dpState: Record<string, any>, options?: SendDpOption) => any) => (dpState: Record<string, any>, options?: SendDpOption) => any` | dp-kit publishDps interceptor; can be used standalone if needed. |
| `destroy` | `() => void` | Destroy dp-kit and clean up resources such as flush timers and throttling/debouncing maps. Should be called when SmartDeviceModel is destroyed (e.g., in SdmProvider's useEffect cleanup). |

##### `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 |

##### `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` 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` 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` OnDeviceInfoUpdatedInterceptor

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

##### `type` OnDpDataChangeInterceptor

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

##### `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` 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` DpValue

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

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

##### `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` OnDeviceOnlineStatusUpdateInterceptor

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

##### `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` 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` PublishDpsOptions

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

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

##### `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` 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` 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` 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` 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

#### Basic usage.

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

const schema = [
  { code: 'switch_1', type: 'bool' },
  { code: 'colour_data', type: 'raw' },
] as const;

const dpKit = createDpKit<typeof schema>({
  protocols: {
    colour_data: {
      parser: raw => JSON.parse(raw),
      formatter: structured => JSON.stringify(structured),
    },
  },
});

const sdm = new SmartDeviceModel<typeof schema>({
  interceptors: dpKit.interceptors,
});

await sdm.init();
dpKit.init(sdm);
```

#### Includes protocol parsing and throttling

```ts
const dpKit = createDpKit<typeof schema>({
  protocols: {
    colour_data: {
      parser: raw => JSON.parse(raw),
      formatter: value => JSON.stringify(value),
    },
  },
  sendDpOption: {
    throttle: 300,
  },
});

const device = new SmartDeviceModel<typeof schema>({
  interceptors: dpKit.interceptors,
});

await device.init();
dpKit.init(device);

// All subsequent sends inherit 300ms throttling
await device.publishDps({
  colour_data: { hue: 240, saturation: 1000, value: 1000 },
});
```

#### Ignore device report responses

```ts
const dpKit = createDpKit<typeof schema>({
  sendDpOption: {
    immediate: true,
    ignoreDpDataResponse: {
      timeout: 5000,
      whiteDpCodes: ['switch_1'],
    },
  },
});

const device = new SmartDeviceModel<typeof schema>({
  interceptors: dpKit.interceptors,
});
```

#### Use with hooks

```tsx
import { useStructuredActions, useStructuredProps } from '@ray-js/panel-sdk';

const colour = useStructuredProps(props => props.colour_data);
const actions = useStructuredActions();

actions.colour_data.set({
  hue: colour.hue,
  saturation: colour.saturation,
  value: 800,
});
```
