Last Updated on : 2024-06-25 03:42:25download
Data point (DP) is a data model defined by the Tuya Developer Platform to describe the functions of a product. The abstract descriptions of device properties and functions help to standardize and manage a myriad of smart devices in a unified way. Describing a device with a set of DPs can shield the differences between underlying hardware for low coupling.
When adding a DP on the Tuya Developer Platform, you can choose its data type and data transfer type.
DP data types:
Object type:
Boolean
Represent the values that can be only true or false. For example, the on and off state for a switch.
Value
Represent the values that can be linearly adjusted. For example, the temperature ranges from 20°C to 40°C.
Enum
A custom finite set of values. For example, operation modes can be low, medium, and high.
Bitmap
Report multiple states, specifically for device faults.
String
Transfer data in string format with a maximum of 255 bytes, typically used for complex features.
Raw type
Transfer data in hexadecimal format, typically used for complex features.
Extended DP properties:
Passive reporting
The module can report DP data only when it receives a command. This can avoid frequent data reporting.
Repeated reporting
Enabling this feature allows the DP to repeatedly report identical values. Otherwise, the framework will filter them out.
DP routing
Control which channel a cellular and Bluetooth combo device uses for DP data transmission.
If it is not specified, the cellular network is preferred. If the cellular network is not available, Bluetooth is used.
1
: Bluetooth is preferred. If Bluetooth is disconnected, the cellular network is used.
2
: Force the use of Bluetooth. If Bluetooth LE is disconnected, the app panel will display an error message.
DP data transfer type:
DP timeliness:
Real-time DP:
This type of DP is time-critical, used to report or receive real-time DP data. The time at which the DP data is generated is exactly when it is reported. For example, control the on/off state of a switch and then synchronize the current state with the cloud and client.
Record-type DP:
This type of DP is used to record the device status and the generated data. The time at which the DP data is generated does not align with when it is reported. For example, the door unlocking records, alerts, and power usage.
You can call data reporting APIs provided by the framework to synchronize the status of devices and local data, such as on/off state and battery level, with the cloud and client.
The APIs will verify the validity of the DP and automatically determine the reporting channel based on network conditions. The DP data can be reported either synchronously or asynchronously.
Asynchronous reporting
The framework caches the data to be reported and delivers it when the reporting thread is scheduled, without blocking the application thread. If you only need the last reporting to reflect the actual status of the device and do not care about how many times DP data is reported, you can choose this reporting method. For example, report on/off state.
Synchronous reporting
The framework instantly reports data, but this can block the application thread and does not filter out identical DP values. Use this reporting method if you need to control the number of times DP is reported and the application requires immediate knowledge of the reporting result to respond accordingly. For example, when measurement data such as electricity usage fails to report, the application caches the data and reports it next time.
DPs of raw type only support synchronous reporting.
The framework uses callbacks to notify the application that there are DP commands to handle. There are three callbacks used for the object-type DP, raw-type DP, and DP query respectively. They are registered by the application during device initialization.
The data packet to synchronize includes a synchronization identifier to differentiate it from the proactively reported one, preventing unintended triggering of scene linkage.
The device needs to periodically synchronize its status with the cloud and client to maintain consistency. The device can either proactively synchronize its status or respond to a status query.
Proactive synchronization
In the following cases, the device proactively synchronizes the cached object-type DP data.
Proactive synchronization does not apply to the raw-type DP data because it cannot be cached.
Query-triggered synchronization
The device responds to the query from the cloud or client with the status of the specified DP. The framework notifies the application of the query through the DP query processing callback. The application calls the appropriate query-triggered reporting API to report data.
Repeatedly reporting data of a DP within a time period can cause a waste of cloud resources. To prevent this, DP throttling limits the number of DP reporting requests allowed within a specific time window.
A single DP can be reported up to 200 times within 60 seconds by default. When this limit is reached, throttling will be triggered to prevent further data reporting. Reporting will resume when the next cycle starts.
--> --> C["Update object- --> --> --> F["Reporting ends"] ```
```mermaid graph LR; B["Device activated"]-- --> C["Available channel exists"] C-- --> D["Validity check passed"] D-- --> E["No throttling"] E-- --> F["Not filter DP"] F-- --> G["Check passed"] ```
After receiving the object-type DP command, the framework compares the received DP value with the cached one. If they are consistent, the framework will start synchronizing DP data, without invoking a callback to notify the application.
If it is raw-type data or no valid cached value exists in the framework, the application will get notified to handle the subsequent process.
```mermaid
graph LR;
A["Receive DP data
--> C{"The DP value does not
match the cached one"}
C -- --> E["Notify the application
--> F["Application processes
--> --> G
C -- --> C1
```
```mermaid
graph LR;
A("Start") --> B("Select a channel") --> C("Assemble data packet") --> D("Send data packet to
the target channel") --> E{"Data is reported"}
E -- --> F("End")
E -- --> F1["Start a 2- --> B
```
The rule to specify the timestamp when reporting DP data:
To report real-time DP, set the timestamp to 0
. The framework will automatically use the time when data is reported as the timestamp.
To report record-type DP, set the time when the DP record is generated as the timestamp.
/**
* @brief Definition of dp property type
*/
typedef BYTE_T DP_PROP_TP_E;
#define PROP_BOOL 0
#define PROP_VALUE 1
#define PROP_STR 2
#define PROP_ENUM 3
#define PROP_BITMAP 4
// A union of DP values
typedef union {
INT_T dp_value; // valid when dp type is value
UINT_T dp_enum; // valid when dp type is enum
CHAR_T *dp_str; // valid when dp type is str
BOOL_T dp_bool; // valid when dp type is bool
UINT_T dp_bitmap; // valid when dp type is bitmap
} TY_OBJ_DP_VALUE_U;
typedef struct {
/** dp ID */
BYTE_T dpid;
/** dp type, see DP_PROP_TP_E */
DP_PROP_TP_E type;
/** dp value, see TY_OBJ_DP_VALUE_U */
TY_OBJ_DP_VALUE_U value;
/** dp happen time. if 0, mean now */
UINT_T time_stamp;
} TY_OBJ_DP_S;
After receiving the DP command notification, the application can get information about the command from the struct, such as the command source and transfer type.
cid
:
A common device
cid
is fixed to NULL.
A gateway device
When cid
is NULL, the DP command is intended for the gateway.
When
cid has a value, the value is the ID of a sub-device and the DP command is intended for this sub-device.
mb_id
:
The group ID, used for gateway devices.
/**
* @brief tuya sdk dp cmd type
*/
typedef BYTE_T DP_CMD_TYPE_E;
#define DP_CMD_LAN 0 // cmd from LAN
#define DP_CMD_MQ 1 // cmd from MQTT
#define DP_CMD_TIMER 2 // cmd from Local Timer
#define DP_CMD_SCENE_LINKAGE 3 // cmd from scene linkage
#define DP_CMD_RELIABLE_TRANSFER 4 // cmd from reliable transfer
#define DP_CMD_BT 5 // cmd from bt
#define DP_CMD_SCENE_LINKAGE_LAN 6 // cmd from lan scene linkage
#define DP_CMD_FFC 7 // cmd from ffc
/**
* @brief tuya sdk dp trans type
*/
typedef BYTE_T DP_TRANS_TYPE_T;
#define DTT_SCT_UNC 0 // unicast
#define DTT_SCT_BNC 1 // boardcast
#define DTT_SCT_MNC 2 // multicast
#define DTT_SCT_SCENE 3 // scene
/**
* @brief Definition of recved structured dp
*/
typedef struct {
/** see DP_CMD_TYPE_E */
DP_CMD_TYPE_E cmd_tp;
/** see DP_TRANS_TYPE_T */
DP_TRANS_TYPE_T dtt_tp;
/** if(NULL == cid) then the cid represents gwid */
CHAR_T *cid;
/** mb ID */
CHAR_T *mb_id;
/** count of dp */
UINT_T dps_cnt;
/** the dp data */
TY_OBJ_DP_S dps[0];
} TY_RECV_OBJ_DP_S;
/**
* @brief Definition of recved raw dp
*/
typedef struct {
/** see DP_CMD_TYPE_E */
DP_CMD_TYPE_E cmd_tp;
/** see DP_TRANS_TYPE_T */
DP_TRANS_TYPE_T dtt_tp;
/** if(NULL == cid) then the cid represents gwid */
CHAR_T *cid;
/** dp ID */
BYTE_T dpid;
/** mb ID */
CHAR_T *mb_id;
/** data len */
UINT_T len;
/** the data */
BYTE_T data[0];
} TY_RECV_RAW_DP_S;
/**
* @brief Definition of dp report type
*/
typedef BYTE_T DP_REPT_TYPE_E;
#define T_OBJ_REPT 0 // dp is value,str,enum,bool,bitmap
#define T_RAW_REPT 1 // raw type
#define T_STAT_REPT 2 // stat type
#define T_RE_TRANS_REPT 10 // repeat report
typedef struct {
/** report type, see DP_REPT_TYPE_E */
DP_REPT_TYPE_E dp_rept_type;
/** obj: is TY_OBJ_DP_REPT_S, stat: dp is TY_STAT_DP_REPT_S, RAW: TY_RAW_DP_REPT_S */
VOID_T* dp_data;
/** Json decoded dp string */
CHAR_T* dp_data_json;
/** is query or not */
BYTE_T is_query;
} DP_REPT_CB_DATA;
tuya_iot_com_api.h
Report DP data
After device initialization, call the appropriate reporting API to report DP data.
Process received DP commands
During device initialization, the application registers the callbacks for processing object-type and raw-type DP commands.
Respond to DP queries
During device initialization, the application registers the callback for processing DP queries. In the callback, the query-triggered reporting API is called to return DP data.
The asynchronous reporting API verifies the DP data and, if successful, updates the cached data. It then assembles a packet and triggers the appropriate reporting event.
A successful response from the asynchronous reporting API only indicates that the reporting event was triggered successfully. It does not necessarily mean that the DP data has been successfully reported.
Method 1: Standard reporting
The API enables/disables filtering based on the configuration of repeated reporting on the Tuya Developer Platform.
/**
* @brief dev_report_dp_json_async
* @desc report dp info a-synced.
*
* @param[in] dev_id: if sub-device, then devid = sub-device_id
* if gateway/soc/mcu, then devid = NULL
* @param[in] dp_data: dp array header
* @param[in] cnt: dp array count
*
* @return OPRT_OK: success Other: fail
*/
OPERATE_RET dev_report_dp_json_async(IN CONST CHAR_T *dev_id, IN CONST TY_OBJ_DP_S *dp_data, IN CONST UINT_T cnt);
Method 2: Forced reporting
This API does not enable filtering. It reports data regardless of the configuration of repeated reporting on the Tuya Developer Platform.
/**
* @brief dev_report_dp_json_async_force
* @desc report dp info a-synced.
*
* @param[in] dev_id: if sub-device, then devid = sub-device_id
* if gateway/soc/mcu, then devid = NULL
* @param[in] dp_data: dp array header
* @param[in] cnt: dp array count
*
* @return OPRT_OK: success Other: fail
*/
OPERATE_RET dev_report_dp_json_async_force(IN CONST CHAR_T *dev_id, IN CONST TY_OBJ_DP_S *dp_data, IN CONST UINT_T cnt);
The synchronous reporting API verifies the DP data and, if successful, reports the DP data immediately. The return value of the API call can indicate if the data is successfully reported. Record-type data is typically reported using this API. If the data fails to report, you need to store or accumulate it. Then, start a thread or timer to attempt reporting periodically. Repeat this process until data is successfully reported, and then delete the record or clear the data.
The synchronous reporting API can block the application thread, requiring a large stack depth of the application. The blocking time can be specified with the API parameter, usually set to five seconds.
/**
* @brief dev_report_dp_stat_sync_extend
* @desc: report dp status info synced.
* if time_stamp==0, time_stamp = time of msg arrival of the server
*
* @param[in] dev_id: if sub-device, then devid = sub-device_id
* if gateway/soc/mcu, then devid = NULL
* @param[in] dp_data: dp status array header
* @param[in] cnt: dp status array count
* @param[in] timeout: function blocks until timeout seconds
* @param[in] enable_auto_retrans
*
* @return OPRT_OK: success Other: fail
*/
OPERATE_RET dev_report_dp_stat_sync_extend(IN CONST CHAR_T *dev_id, IN CONST TY_OBJ_DP_S *dp_data,
IN CONST UINT_T cnt, IN CONST UINT_T timeout, IN CONST BOOL_T enable_auto_retrans);
#define dev_report_dp_stat_sync(dev_id, dp_data, cnt, timeout) \
dev_report_dp_stat_sync_extend(dev_id, dp_data, cnt, timeout, TRUE)
This API is used to report data in response to an object-type DP query. The data packet includes a synchronization identifier to differentiate it from the proactively reported one, preventing unintended triggering of scene linkage.
/**
* @brief dev_query_dp_json_async
* @desc report dp info a-synced.
*
* @param[in] dev_id: if sub-device, then devid = sub-device_id
* if gateway/soc/mcu, then devid = NULL
* @param[in] dp_data: dp array header
* @param[in] cnt: dp array count
*
* @return OPRT_OK: success Other: fail
*/
OPERATE_RET dev_query_dp_json_async(IN CONST CHAR_T *dev_id, IN CONST TY_OBJ_DP_S *dp_data, IN CONST UINT_T cnt);
/**
* @brief dev_query_dp_json_async_force
* @desc report dp info a-synced.
*
* @param[in] dev_id: if sub-device, then devid = sub-device_id
* if gateway/soc/mcu, then devid = NULL
* @param[in] dp_data: dp array header
* @param[in] cnt: dp array count
*
* @return OPRT_OK: success Other: fail
*/
OPERATE_RET dev_query_dp_json_async_force(IN CONST CHAR_T *dev_id, IN CONST TY_OBJ_DP_S *dp_data, IN CONST UINT_T cnt);
The raw-type DP only supports synchronous reporting, and the framework does not cache the raw-type DP data. Therefore, filtering and data synchronization mechanism do not apply.
Method 1: Without timestamp
Scenario: The time at which the DP data is generated is exactly when it is reported.
/**
* @brief dev_report_dp_raw_sync_extend
* @desc report dp raw info synced.
*
* @param[in] dev_id: if sub-device, then devid = sub-device_id
* if gateway/soc/mcu, then devid = NULL
* @param[in] dpid: raw dp ID
* @param[in] data: raw data
* @param[in] len: len of raw data
* @param[in] timeout: function blocks until timeout seconds
* @param[in] enable_auto_retrans
*
* @return OPRT_OK: success Other: fail
*/
OPERATE_RET dev_report_dp_raw_sync_extend(IN CONST CHAR_T *dev_id, IN CONST BYTE_T dpid,
IN CONST BYTE_T *data, IN CONST UINT_T len,
IN CONST UINT_T timeout, IN CONST BOOL_T enable_auto_retrans);
#define dev_report_dp_raw_sync(dev_id, dpid, data, len, timeout) \
dev_report_dp_raw_sync_extend(dev_id, dpid, data, len, timeout, TRUE)
Method 2: With timestamp
Scenario: The time at which the DP data is generated does not align with when it is reported.
/**
* @brief dev_report_dp_raw_sync_extend_with_time
* @desc report dp raw info synced.
*
* @param[in] dev_id: if sub-device, then devid = sub-device_id
* if gateway/soc/mcu, then devid = NULL
* @param[in] dpid: raw dp ID
* @param[in] data: raw data
* @param[in] len: len of raw data
* @param[in] timeout: function blocks until timeout seconds
* @param[in] enable_auto_retrans
* @param[in] time_str
*
* @return OPRT_OK: success Other: fail
*/
OPERATE_RET dev_report_dp_raw_sync_extend_with_time(IN CONST CHAR_T *dev_id, IN CONST BYTE_T dpid,
IN CONST BYTE_T *data, IN CONST UINT_T len,
IN CONST UINT_T timeout, IN CONST BOOL_T enable_auto_retrans,
IN CONST CHAR_T *time_str);
#define dev_report_dp_raw_sync_with_time(dev_id, dpid, data, len, timeout, time_str) \
dev_report_dp_raw_sync_extend_with_time(dev_id, dpid, data, len, timeout, TRUE, time_str)
Boolean DP: true or false.
Value DP: stored and transmitted as an integer. The range of values is from -2147483648 to 2147483647.
Enum DP: 0 to (the number of enum objects − 1).
String DP: no more than 255 bytes.
Raw DP: typically, no more than 255 bytes. But the maximum length can be 1,024 bytes.
Modifying the DP after mass production is not recommended, as it can cause certain functions of the device not to work or make the device completely unusable.
TuyaOS v3.3.0 or later supports adding DP on the fly. The changes take effect after the device is restarted.
If your framework is earlier than v3.3.0, or if you delete or modify a DP, the changes take effect after the device is reset and paired.
The device processes the DP of the value type as integers. It expands a value with a fractional part to write it as an integer.
You can set the scale of a DP on the Tuya Developer Platform to enable the client to divide the received value by the scale to get the original value. Suppose that the actual value has three decimal places. You can set scale to 3
. The client divides the received value by 1,000 and displays the result.
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback