跳至主要內容

属性下发预处理规则

约 1286 字大约 4 分钟

属性下发预处理规则

属性下发预处理规则 的触发时间,是在云平台向设备端实际下发属性之前。适合用于对设备下发属性做必要的内容增减、格式转换、二次计算等。

目前支持的操作如下:

  • 预处理函数

预处理函数

提供了可编程的云函数,支持 Javascript 编程语言,如下:

 module.exports = function (push_attributes) {
    /**
     * push_attributes:   下发的属性对象,同时作为函数返回值。函数中可更新属性对象。
     */

    return push_attributes;
} 

提示

当您在消息规则中编辑云函数时,可以多多使用在线调试功能,帮助您验证代码的准确性,并提升开发速度。详细介绍请浏览:每日调用上亿次的消息规则云函数,如何在线测试?open in new window

示例:自动实现多个继电器互斥

这是一个最简单的例子,帮助您快速了解属性下发预处理的工作机制。

某设备端有两个继电器,属性分别是 relay1relay2,我们希望两个继电器总是互斥。

编写属性下发预处理函数如下:

 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 设置为互斥模式时,两个继电器 relay1relay2 总是互斥。

修改预处理函数如下:

 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;
}