DP (Data Point): Definition, Creation, and Usage

A DP (Data Point) is Tuya's abstraction of a product capability and the contract for every piece of data flowing between the device and the cloud. This guide explains what a DP is, its key characteristics, how to create DPs on the Tuya Developer Platform, how to report and receive DPs in agentic-kit, and closes with a roundup of official and on-site references.

What Is a DP​

The official documentation defines a DP at three levels (quoted passages are English translations of the Chinese originals):

  • Capability abstraction — Basic DP (TuyaOS docs): a DP, also called a function point, "describes a capability of a device. The Tuya Developer Platform abstracts all device capabilities into function points, supporting Value, Boolean, Enum, String, Fault, and Raw (pass-through) types."
  • Data model — Terminologies (TuyaOpen docs): a DP is Tuya's data model for product capability definitions, used to describe the functions of a product.
  • Data contract — Agent Development Guide (TuyaOpen docs): a DP defines every piece of data flowing between the device and the cloud — sensor readings, switch states, raw binary payloads, and so on. An Agent observes and controls a device by reading and writing DPs.

Take a two-gang switch: its capabilities are abstracted as two DPs, each of Boolean type. A DP carries read/write semantics — read fetches the current value, write changes it. When the app turns on the first gang, it writes true to DP 1; when the device reports the actual switch states to the cloud, the app and the Agent can see the latest state.

Key Characteristics of a DP​

The Four Elements​

ElementDescriptionExample
DPIDNumeric identifier, 1–255; functional data between the device and the cloud is transported by DPID1, 2, 101
DPCodeHuman-readable identifier: letters, digits, and underscores, starting with a letter; aimed at the application layer and multilingual scenariosswitch_1, temp_current, color_mode
Data typeOne of the six official types (see below)Boolean
Constraintmin/max/step/scale/unit for Value; the value set for Enum0–100, step 1, unit %

Standard functions (also called standard DPCodes) are the function points with DPIDs below 100; see Creating DPs.

The Six Data Types​

TypeMeaningExample
BooleanEither true or falseSwitch on/off
ValueA linearly adjustable number with range, step, and unitTemperature 20–40 °C
EnumA custom, finite value setLow/Medium/High
FaultFor reporting and counting faults; supports multiple faults; report-onlyDry burn, sensor fault
StringTextVersion string, status description
RawProduct functions passed through as binaryRaw sensor data frame

Data Transfer Modes​

ModeOfficial definition
Read/write (rw)Commands can be sent to the device, and device data can be transmitted to the cloud
Report-only (ro)Data can only travel from the device to the cloud
Write-only (wr)Data can only be sent from the cloud to the device

Message Formats​

On the Wi-Fi/cloud link, DPs travel as dps JSON whose keys are DPIDs in string form:

{"dps": {"1": true, "2": 25}}

On the cloud side, a DP is described by DPCode + type + constraints: functions is the command set that can be sent to the device, and there is a structurally identical status state set that can be reported (omitted here). Excerpt from the electric pressure cooker category in the official docs:

{
"result": {
"category": "dylg",
"functions": [
{"code": "switch", "type": "Boolean", "values": "{}"},
{"code": "appointment_time", "type": "Integer",
"values": "{\"unit\":\"min\",\"min\":0,\"max\":1440,\"scale\":0,\"step\":1}"}
]
}
}

The cloud open-platform API for sending device commands is POST /v1.0/iot-03/devices/{device_id}/commands with body {"commands":[{"code":"<dpCode>","value":...}]} — the cloud-side semantics use the DPCode. The Bluetooth link uses binary frames instead: dp_id (1 byte) + dp_type (1 byte) + dp_data_len (2 bytes) + dp_data_value, with the on-wire type codes raw=0, bool=1, value=2, string=3, enum=4, and bitmap (Fault)=5.

A DP is a contract shared by three parties

DP definitions are shared by the device firmware, the Tuya cloud, and the app/Agent; changing only one of them breaks communication. Design guidance: model DPs after semantic capabilities rather than register values; keep DPCodes human-readable (hvac_mode over dp5 — Agents/LLMs understand them by name); have the Agent read state before acting; keep control DPs idempotent (writes are retried on network failures).

Cloud rate limits

A single DPID may report at most 3500 messages per day and 1200 per 10 minutes; exceeding the limit gets throttled by the cloud, so merge changes into fewer reports. Also, after the app sends a DP, the device must report the corresponding DP before the app display updates.

Creating DPs​

DPs are created on the Tuya IoT Platform as part of product function definition:

  1. Go to Product Development and create a product under a category.
  2. Under 01 Function Definition > Product Functions, add functions: pick from the standard function library, or create custom functions.
  3. For each function, fill in the DPCode, choose the data type, and set the constraints — each function becomes one DP.
  4. Once the function definition is done, move on to firmware development and debugging (wiring the schema into agentic-kit, below).

The platform groups product functions into three classes:

ClassDescription
Standard functionsCommon functions of a product category, also called standard DPCodes (DPIDs below 100)
Custom functionsFunction points you define for your product
Advanced functionsFunctions that do not fit the common expression formats, such as cloud timers and web links
Custom functions + Agents: one extra step

If the product contains custom function points that an Agent will use, you must also configure autonomous-control commands under AI product command configuration on the platform. Products using only standard functions (DPIDs below 100) are configured by default.

An example function worksheet (modeled on the electric pressure cooker in the official docs):

FunctionDPCodeData typeTransfer modeNotes
SwitchswitchBooleanRead/writeMaster on/off
Appointment timeappointment_timeValueRead/write0–1440 min, step 1
Cooking modecook_modeEnumRead/writeRice/Porridge/Soup
Pot temperaturetemp_currentValueReport-onlyLive temperature
FaultfaultFaultReport-onlyDry burn/sensor fault, multiple fault bits

Using DPs in agentic-kit​

The schema is the JSON expression of the platform's product function definition: per DP it describes the id, the mode (rw/ro/wr), and the property (data type and constraints). It is obtained from the activation response or exported from the platform.

Three Ways the Schema Reaches the Device​

PathWhenDescription
First activationActivation responseCarries the schema and schema_id (see examples/posix/pair/api-activate/)
Restore on rebootAt startupFed back through the schema/schema_id/dp_state fields of iot_client_config_t; iot_client_init() rebuilds the DP registry and restores state automatically (no dirty bit, no report)
Runtime upgradePeriodic pollingiot_dp_schema_check_update() fetches the newest schema, keeps the current values of DPs that still exist, fills defaults for new DPs, and fires the update callback

The Device-Side Schema​

The device consumes the real Tuya schema format (taken from examples/posix/dp-management/):

[
{"mode":"rw","property":{"type":"bool"},"id":1,"type":"obj"},
{"mode":"ro","property":{"min":0,"max":100,"scale":0,"step":1,"type":"value"},"id":2,"type":"obj"},
{"mode":"rw","property":{"min":0,"max":100,"scale":0,"step":1,"type":"value"},"id":3,"type":"obj"},
{"mode":"ro","property":{"range":["none","charging","charge_done"],"type":"enum"},"id":4,"type":"obj"},
{"mode":"ro","property":{"type":"raw"},"id":5,"type":"obj"}
]

The top-level type:"obj" marks an object DP; the data type lives in property.type. mode is rw/ro/wr, matching the transfer modes above.

Type and Constraint Mapping​

Official typeiot_dp_type_tStorage
BooleanIOT_DP_TYPE_BOOLbool
ValueIOT_DP_TYPE_VALUEint32_t, strictly validated against vmin/vmax
EnumIOT_DP_TYPE_ENUMIndex into the schema range[]
StringIOT_DP_TYPE_STRINGUTF-8 string, optional maxlen
RawIOT_DP_TYPE_RAWOpaque bytes, optional maxlen
Fault—Not modeled separately in the current version

Constraint mapping: property.min/max → vmin/vmax (strictly validated); the Enum range → the table of legal values; maxlen for raw/string.

Core API​

APIPurpose
iot_dp_set()Write a value locally and mark it dirty; does not report
iot_dp_get()Read the current cached value
iot_dp_report()Validate and immediately report a single DP
iot_dp_report_all()Report every known DP; the application must call it once after every connect/reconnect
iot_dp_report_all_dirty()Report every currently dirty DP — those set locally and those left dirty by a failed report — in one batched message
iot_dp_set_callback()Register the cloud downlink callback, dispatched per DP
iot_dp_validate_json()Validate a {"dps":{...}} payload against the schema
iot_dp_dump_json() / iot_dp_restore_json()Export/restore the DP state snapshot (RAW excluded)
iot_dp_set_save_callback()Persistence callback pushed on every DP write (fires even when the value is unchanged)
iot_dp_schema_check_update()Poll for a schema upgrade
iot_dp_set_schema_update_callback()Register the schema-upgrade notification callback

All signatures are authoritative in modules/iot-client/include/iot_dp.h.

A Typical Code Flow​

Adapted from examples/posix/dp-management/dp_management_demo.c:

/* Cloud downlink callback: dispatched per dp_id; value is valid only during the call */
static void on_dp_downlink(uint8_t dp_id, const iot_dp_value_t *value, void *ud)
{
/* Drive hardware/UI here */
}

/* 1. init: rebuild the DP registry from the persisted schema,
* then restore DP state after validating it */
iot_client_config_t cfg = {
.schema = saved_schema, /* the product schema from the platform */
.schema_id = saved_schema_id,
.mqtt_disable_auto_connect = true, /* the application owns connect timing */
/* devid / secret_key / local_key / region / env ... */
};
iot_client_t *client = iot_client_init(&cfg);
if (saved_dp_state && iot_dp_validate_json(client, saved_dp_state) == OPRT_OK) {
iot_dp_restore_json(client, saved_dp_state); /* restore cache, no report */
}
iot_dp_set_callback(client, on_dp_downlink, NULL);
iot_dp_set_save_callback(client, on_dp_save, NULL); /* persist on every write */
iot_dp_set_schema_update_callback(client, on_schema_update, NULL); /* schema-upgrade notice */

/* 2. Right after connecting, report the full state — the cloud only trusts device reports */
iot_client_connect(client);
iot_dp_report_all(client);

/* 3. Steady-state loop */
while (g_running) {
iot_client_process(client, 200); /* pump the receive path, dispatch downlinks */

iot_dp_value_t v = { .type = IOT_DP_TYPE_VALUE, .value.integer = 87 };
iot_dp_set(client, 2, &v); /* local change, marks dirty */
iot_dp_report_all_dirty(client); /* batch-report dirty DPs */

iot_dp_schema_check_update(client); /* poll for schema upgrades */
}
Behavior notes

The schema mode is not enforced — mode is a cloud/app-side hint that the device SDK does not check: the device may set/report any DP, and the cloud may send any DP via downlink.

id/type must match the product definition on the platform, otherwise the cloud rejects reports.

RAW is reported as base64 and never enters the persistence snapshot (a dump/restore round trip loses RAW values).

report_all after every connect/reconnect — restored values are not reported automatically; failed reports keep their dirty bit for retry; an oversized payload returns OPRT_DP_PAYLOAD_TOO_LARGE and must be split with iot_dp_report(); with an empty or missing schema the layer runs in loose pass-through mode (no validation).

For a complete runnable sample see examples/posix/dp-management/; for obtaining the schema at activation see examples/posix/pair/api-activate/; for using DPs inside an AI session see examples/posix/ai/rtc-tcp-client/agent_trigger_demo.c. The full procedure for saving and restoring DP state across reboots is covered in DP State Persistence.

DP or Device-Side MCP​

Use DPs for stable, enumerable device capabilities and states (switches, brightness, temperature, modes) — the main callers are apps, cloud automations, and device linkages. Use device-side MCP for dynamic, task-shaped tools with complex parameters (reading sensors, taking photos, driving motors) — the main caller is the AI Agent. The two can coexist in one product; for the decision criteria see Core Concepts: Physical device control — DPs and device-side MCP.

References​

Official documentation:

On this site:

© 2026 Tuya Inc.Tuya Physical AI · Agentic-kit