自定义节点


自定义节点

自定义节点是我们的物联网低代码开发中的最核心概念之一,它不仅仅代表着功能的扩展,更重要的是达成系统模块化的关键途径。

基本使用

最基本的自定义节点使用方式是创建一个新工作流,并组合使用一些现有的节点。

像如下这就是一个组合使用了现有的 greater 和 less 节点所创建的 between 自定义节点:

custom-node-between

基本的要点如下:

  1. 创建一个新的工作流(点击菜单文件 --> 新工作流,或者点击项目管理窗格上的新建工作流按钮);

  2. 添加现有的节点,这里我们用到了三个运算节点:greater,less,xor;

  3. 为自定义节点添加输入和输出端口,我们添加了一个 input-number 节点和一个 output-boolean 节点;

  4. 搞定,这个自定义节点可以开始使用了;

我们只要保存并关闭当前的这个工作流,然后在另一个工作流(比如 main)中添加刚刚创建的 between 节点。大体结构如下:

custom-node-usage

当前我们为这个 between 节点硬编码了范围数值,这显然是不实用的。我们也可以为这个自定义节点添加一些参数端口:

custom-node-with-params

如上图,我们可以看到现在这个数值范围已经可以在使用时进行设置了。

custom-node-usage-with-params

泛型节点

当我们实现一些处理数据的节点时,通常会需要跟不同的数据类型打交道。比如内置的 equal 节点,我们当然不希望需要为每一个不同的数据类型都提供一份相应的实现,比如 equal-boolean,equal-number,equal-string 等等。

Ticos Studio 对于泛型类型提供了较好的支持,可以有效的避免上面的这种重复实现的情况。泛型的使用略微有些复杂,因此我们单独写了一篇文档进阶话题 - 泛型和变参介绍此重要特性。

使用 C++

当我们无法使用内置节点的组合来完成我们的自定义节点的目标时,可以考虑使用 C++ 来进行更大自由度的开发。而且使用 C++ 代码通常也代表着更高的运行性能。

cpp-node

使用 C++ 代码的基本方法很简单,就是在工作流里引入一个叫 not-implemented-in-ticos 的节点,然后双击这个节点会进入到 C++ 代码的编写环境。

node {
    // Internal state variables defined at this level persists across evaluations
    Number foo;
    uint8_t bar = 5;

    void evaluate(Context ctx) {
        bar += 42;

        if (isSettingUp()) {
            // This run once
            foo = (Number)(bar + 1);
        }

        auto inValue = getValue<input_IN>(ctx);
        emitValue<output_OUT>(ctx, inValue);
    }
}

以下是一个对上述缺省 C++ 代码修改计算 cos 值的例子:

node {
    // The `evaluate` function is the node’s entry point. It is the only
    // function XOD requires to implement. The context parameter is a
    // black-box object you’ll pass to various API functions.
    void evaluate(Context ctx) {
        // `getValue` function reads a pin. In angle brackets, it takes a
        // name of the pin in form input_PINLABEL (input_RAD in our case)
        Number x = getValue<input_RAD>(ctx);

        // Next, we use regular C++ to perform some actions. Our case is trivial.
        // All we have to do is to call the standard C++ cos function.
        // Note the data type `Number`. It’s the type XOD uses to represent numbers
        // on the current platform.
        Number result = cos(x);

        // `emitValue` is like `getValue`, but it writes values rather than read.
        // Note we use `OUT` label to access our unlabeled output terminal.
        // `OUT` is the default name when you omit the label.
        emitValue<output_OUT>(ctx, result);
    }
}

可以看到 C++ 节点的代码基本上可以分为很清晰的三步:

  1. 从输入端口取得参数;

  2. 将输入参数传给已封装好的 C++ 库函数或者方法,获得返回值;

  3. 将返回值作为结果,吐给输出端口;

因为 Ticos Studio 不是专业的 C++ IDE,因此我们不建议在 C++ 节点里编写过于复杂的代码,而是应该在 Visual Studio 等 IDE 中将需要实现的 C++ 逻辑编写并测试好,然后封装为一个静态库,并在 Ticos Studio 中引入。这样可以一直保持 C++ 节点简单明了。

需要注意的是,一旦引入这个 C++ 节点,则该工作流里的其他节点都会被忽略。

更多的 C++ 节点的实现规范,请参考相应的开发规范

自定义节点的复用

我们可以通过发布自定义节点,来达成代码复用的目的。具体方法请参见低代码开发的相关章节

如本文开头所说,自定义节点是我们的物联网低代码开发中的最核心概念之一,它不仅仅代表着功能的扩展,更重要的是达成系统模块化的关键途径。

为了能够真正最大化利用 Ticos Studio 的价值,没有局限性的开发出工业级的优秀硬件产品,熟练掌握自定义节点的开发和使用是必备技能。

上次编辑于: 2022/12/17 07:45:59
Loading...