属性下发预处理规则
属性下发预处理规则
提示
如果您还不了解什么是 ThingsCloud 消息规则,以及消息规则的创建方法,请浏览 消息规则基础。
什么是属性下发预处理规则
属性下发预处理规则 是 ThingsCloud 消息规则的一种。它的触发时机是在云平台向设备端实际下发属性之前。该规则用于对平台即将下发的属性做必要的内容增减、格式转换、二次计算等加工,处理结果将替代原始下发属性,最终下发到设备。
在实际物联网项目中,平台下发的属性往往需要根据业务逻辑进行调整。例如:
- 实现多个继电器之间的互斥控制
- 自动追加时间戳、操作次数等辅助属性
- 根据设备当前属性动态调整本次下发的内容
- 对下发属性进行格式转换或校验
通过属性下发预处理规则,可以在属性实际下发到设备前完成这些加工,让设备端收到更完整、更符合业务需求的属性消息。
下图展示了该规则的触发位置:
提示
如果您还不了解 ThingsCloud 设备属性下发的通信规范,请浏览 设备属性。
触发的条件
属性下发预处理规则需要同时满足以下条件才会触发:
- 平台要向设备下发属性:通过控制台、可视化看板、App 或 API 等方式,触发向设备下发属性的操作。
- 已创建属性下发预处理规则:在该设备或其所属设备类型下,已创建了属性下发预处理规则。
需要特别说明的是:
- 对于同一设备同一则下发消息,平台仅会触发一条属性下发预处理规则。如果需要执行预处理操作,需要将该操作配置在同一条规则中。
- 在属性下发预处理规则中,多个预处理函数按顺序串行执行,前一个函数处理后的属性集合,会作为下一个函数的输入。
- 所有操作处理完成后的属性集合,才会最终下发到设备。
支持的操作
属性下发预处理规则目前支持以下操作:
| 操作名称 | 介绍信息 |
|---|---|
| 预处理函数 | 编写 Javascript 云函数,对平台下发的属性进行任意加工处理。 |
预处理函数
使用预处理函数操作,您可以根据需要来编写相应的云函数,对平台即将下发的属性做任意的处理,处理结果将作为最终下发到设备的属性消息。
module.exports = function (push_attributes) {
/**
* push_attributes: 下发的属性对象,同时作为函数返回值。函数中可更新属性对象。
*/
return push_attributes;
}
提示
当您在消息规则中编辑云函数时,可以多多使用在线调试功能,帮助您验证代码的准确性,并提升开发速度。详细介绍请浏览:每日调用上亿次的消息规则云函数,如何在线测试?。
示例:自动实现多个继电器互斥
这是一个最简单的例子,帮助您快速了解属性下发预处理的工作机制。
某设备端有两个继电器,属性分别是 relay1 和 relay2,我们希望两个继电器总是互斥。
编写属性下发预处理函数如下:
module.exports = function (push_attributes) {
if (push_attributes.relay1 !== undefined) {
push_attributes.relay2 = !push_attributes.relay1;
}
if (push_attributes.relay2 !== undefined) {
push_attributes.relay1 = !push_attributes.relay2;
}
return push_attributes;
}
有了这个属性下发预处理规则后,当我们在平台操作 relay1 闭合,平台原本要下发消息:
{
"relay1": true
}
但由于存在属性下发预处理函数,平台实际会下发的消息是:
{
"relay1": true,
"relay2": false
}
与此同时,在平台的设备属性状态中,也可以看到 relay2 属性值同步更新为 false。
提示
在平台操作 relay1 闭合,具体的方法非常多,例如:
- 在控制台的设备详情页中,点击相应的属性开关。
- 在控制台的可视化看板中,点击相应的属性开关。
- 在控制台的设备调试中,输入下发属性的 JSON。
- 在用户应用 ThingsX App(包括iOS/Android/微信小程序)中,点击相应的属性开关。
- 在用户应用 ThingsXS 的设备详情页中,点击相应的属性开关。
- 编写程序,调用项目 HTTP API,下发响应的属性。
示例:在互斥控制模式下,实现多个继电器互斥
在上边的示例基础上,我们增加一个逻辑,当设备的控制模式属性 control_mode 设置为互斥模式时,两个继电器 relay1 和 relay2 总是互斥。
修改预处理函数如下:
module.exports = function (push_attributes) {
// 读取设备当前所有属性
var attrs = Cloud.getCurrentAttributes();
// 判断控制模式是否为互斥模式
if (attrs.control_mode == 'mutual') {
if (push_attributes.relay1 !== undefined) {
push_attributes.relay2 = !push_attributes.relay1;
}
if (push_attributes.relay2 !== undefined) {
push_attributes.relay1 = !push_attributes.relay2;
}
}
return push_attributes;
}
示例:记录继电器操作次数
假设我们要记录用户对继电器属性 relay1 操作的次数,可以写一个这样的预处理函数,生成 relay1_count 这个属性,统计继电器开关的总下发次数。
module.exports = function (push_attributes) {
if (push_attributes.relay1 !== undefined) {
// 读取设备当前的属性
var curr_attrs = Cloud.getCurrentAttributes();
if (curr_attrs.relay1_count === undefined) {
// 上次计数count不存在,说明是首次下发
push_attributes.relay1_count = 1;
} else {
// 上次计数存在,本次计数+1
push_attributes.relay1_count = curr_attrs.relay1_count + 1;
}
}
return push_attributes;
}
以上函数通过使用 JavaScript 的 || 运算符,还可以进一步简化为:
module.exports = function (push_attributes) {
if (push_attributes.relay1 !== undefined) {
// 读取设备当前的属性
var curr_attrs = Cloud.getCurrentAttributes();
// 本次计数+1,上次计数如果不存在则默认为0
push_attributes.relay1_count = (curr_attrs.relay1_count || 0) + 1;
}
return push_attributes;
}
在此基础上,还可以改为只统计当日的下发次数,思考一下如何实现呢?
示例:记录属性今日下发次数
这个例子中,通过属性下发预处理规则,生成 relay1_count 这个属性,统计继电器属性 relay1 在当日的下发次数。
module.exports = function (push_attributes) {
if (push_attributes.relay1 !== undefined) {
// 读取设备当前的属性
var curr_attrs = Cloud.getCurrentAttributes();
// 读取上次的计数,如果不存在则默认为0
var relay1_count = curr_attrs.relay1_count || 0;
// 判断上一次记录的日期,如果不是今天,则清零
if (curr_attrs.relay1_date !== Cloud.Utils.dateFormat("YYYY-MM-DD")) {
relay1_count = 0;
}
// 本次计数+1
push_attributes.relay1_count = relay1_count + 1;
// 记录今天日期
push_attributes.relay1_date = Cloud.Utils.dateFormat("YYYY-MM-DD");
}
return push_attributes;
}
示例:自动下发服务器时间
某设备端需要在收到平台下发继电器开关动作时,同时下发服务器的时间。我们可以在预处理函数中这样写:
module.exports = function (push_attributes) {
if (push_attributes.relay1 !== undefined) {
push_attributes.relay1_time = Cloud.Utils.dateFormat("YYYY-MM-DD HH:mm:ss");
}
return push_attributes;
}
这样一来,当我们在 ThingsCloud 控制台或用户应用 ThingsX App 中下发继电器开关量时,经过该属性下发预处理函数的处理,设备端实际收到的 JSON 消息,例如:
{
"relay1": true,
"relay1_time": "2023-12-03 15:25:32"
}
以上云函数中用到内置函数 Cloud.Utils.dateFormat。
ThingsCloud 还支持完善的时区设置,假设这里使用 美国东部时区 来生成日期时间,修改如下:
module.exports = function (push_attributes) {
// 在函数开头设置时区
Cloud.Utils.setTimezone("America/New_York");
if (push_attributes.relay1 !== undefined) {
push_attributes.relay1_time = Cloud.Utils.dateFormat("YYYY-MM-DD HH:mm:ss");
}
return push_attributes;
}