Node-RED编程基础

这篇具有很好参考价值的文章主要介绍了Node-RED编程基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Node-RED编程基础

【Node-RED与IoT开发交流】785381620 ,欢迎加入!

前言

Node-RED是一款低代码编程的平台, 可以通过可视化编程的方式实现某些特定功能. 但对于许多初次接触该应用的用户来说, 使用Node-RED编程仍存在一些障碍, 个人认为主要是在以下方面:

  1. 消息模型msg
  2. 上下文context
  3. 函数节点function.

故在此将以上三点进行详细的说明, 希望对各位有所帮助.

在学习使用任何软件/平台时, 官方文档永远是第一选择, 你遇到的几乎所有的问题都可以在官方找到答案, 此外, 对于一些节点, 你可很方便的从info窗口看到最基础的指引.

Node-RED编程基础

消息模型msg

在Node-RED中, 我们通过连线将不同功能的节点连接起来.

有些节点只能接入线, 如debug节点. 这类节点只可以接收其它节点提供的数据, 而不能直接产生任何数据.只可以作为输出使用, 类比扬声器.

Node-RED编程基础

有些节点只可输出线, 如inject节点. 这类节点, 只可以产生数据, 而不能接收任何数据, 只能做输入使用, 类比麦克风.

Node-RED编程基础

有些节点即可输出线, 也可以输入线, 如function节点. 此类节点既可以接收数据, 也可以输出数据, 它一般对输入数据进行处理, 处理完成后, 再从输出端口输出.

Node-RED编程基础

当我们用线将三个节点进行连接后, 这便成为了一个流.

Node-RED编程基础

每一个流通过msg对象进行传递消息, 对象可以理解为一包数据, 其结构一般如下:

{"_msgid":"e701ad8b.c7bb1","payload":1626087545399,"topic":""}

其中_msgid指明了消息的ID, payload指明了消息主体, topic指明了消息主题.

在这个流中, 我们使用inject节点产生一个时间戳1626087545399并将其放到payload的位置(msg.payload = 1626087545399). 此时消息已经变为

{"_msgid":"e701ad8b.c7bb1","payload":1626087545399,"topic":""}

该消息作为输入, 输入函数节点. 函数节点接收到该数据后, 进行处理. 函数的具体逻辑由我们指定, 在上述流中, 函数节点代码如下:


return msg;

函数节点中使用JavaScript进行编程, 在该节点中, 直接将msg返回, 不做任何修改. 此时消息仍为

{"_msgid":"e701ad8b.c7bb1","payload":1626087545399,"topic":""}

该消息作为函数节点的处理结果, 输入debug节点. debug节点在接收到该数据后, 将其在调试窗口输出.

Node-RED编程基础

以上是最为基础的一个流, 主要是想要说明一点: msg对象为消息传递的载体. 如果想要对数据进行处理, 操作这个msg就可以了.

例如, 我们想要改变上述流程, 通过时间戳获取当前的时间. 我们只需要对函数节点进行修改即可.

例如, 我们将函数节点的内容修改如下:

let date = new Date(msg.payload) // 根据时间戳生成Date对象
let hh = date.getHours() // 通过date对象获取时分秒
let mm = date.getMinutes()
let ss = date.getSeconds()

msg.payload = hh + ':' + mm + ':' + ss // 拼接时分秒

return msg;

这样, 时间戳作为输入, 经过以上的处理后就得到对应的时分秒了.

Node-RED编程基础

但有些时候, 你不是对传进来的msg对象进行处理, 或者传入的msg不符合你的需要, 那需要对它进行修改.

你可以创造一个新的对象将它返回, 它叫什么名字无所谓.

a = {
  a: ' ',
  b: ' ',
  c: ' '
}
return a;

也可以对原有的msg对象修修补补.

msg.a = 'a' // msg['a'] = 'a' 两种写法的作用是相同的
return msg;

那么以一个案例结束这一部分吧. 我们做过将时间戳转化为dd:mm:ss的格式, 但如果我们也需要返回小时, 分钟, 秒以供后面的节点调用呢. 可以在脑子中简单的过一下想一下答案. 答案很简单, 在msg对象上增添3个键值对就可以了.

let date = new Date(msg.payload); // 根据时间戳生成Date对象
let hh = date.getHours() // 通过date对象获取时分秒
let mm = date.getMinutes()
let ss = date.getSeconds()

msg.payload = hh + ':' + mm + ':' + ss // 拼接时分秒

msg.hh = hh
msg.mm = mm
msg.ss = ss

return msg;

触发后, 你会发现, 我们后面添加的hh,mm,ss并没有输出, 这是为什么呢. 这是因为debug节点默认输出msg对象中的payload键值对, 其余的并没有显示. 可以通过双击debug节点修改配置.

Node-RED编程基础

这样就得到我们想要结果了.

Node-RED编程基础

Node-RED的消息模型, 大概就是这样了, 希望你有所收获吧, 如果有问题也欢迎在下方提出你的疑问.

上下文Context

对于学习过计算机编程的同学来说, “上下文” 应该是个非常非常常见的术语, 通常用来存储当前操作所处的状态. 在Node-RED也如此, 并且, Node-RED还将上下文分为了3种作用域, Node/Flow/Global.

Node的作用域是在当前节点, Flow是当前流, Global则是全局. 下面展开介绍

Node

你也许会问, 在一个节点内部, 使用Context意义在哪? 直接使用变量不就好了.

我们设想一个场景, 我们需要记录某个函数节点的执行次数, 当达到一定次数后就不再输出. 如果用最基础的变量, 将永远不会结束, 因为每次通过函数节点后, 这个节点的所有变量都会被清空, 再次执行使仍是最初始的状态, 可以理解为这个节点是无状态的. 这时Context的作用就体现出来了, 我们需要Context去记录这个节点的状态.

具体实现如下:

// 若Context中有count则使用count, 无count使用0
let count = context.get('count')||0;

if(count > 5)
    return null
    
count += 1;
context.set('count',count); // 将count放入Context

msg.count = count;

return msg;

执行结果如下:

Node-RED编程基础

在执行5次过后, 即使再次使用inject节点触发, 也不输出任何消息.

Flow

与Node类似, Flow存储整个流的状态, 这里所指的流并不是几个节点串成一条的流, 而是一个面板算作一个流, 例如, 以下5个节点串成两条线, 但处一个Tab中, 那么这5个节点共享同一个Flow的Context.

Node-RED编程基础

Flow的应用场景很多, 例如, 我们通过MQTT接收到温湿度传感器传来的数据, 同时, 如果外界通过HTTP协议访问温湿度数据时, 我们就可以通过如下Flow去实现.

Node-RED编程基础

MQTT收到数据后, 将会把数据放入Flow中, 收到HTTP请求后, 会去Flow中查询响应的数据并做返回.

Node-RED编程基础

完整的流如下, 可以自行导入查看:

[{"id":"5ae2bdf8.c1b644","type":"mqtt in","z":"77db09d1.403ba8","name":"","topic":"sensor","qos":"2","datatype":"auto","broker":"c97be055.a659d","nl":false,"rap":true,"rh":0,"x":150,"y":4660,"wires":[["16b09f20.3b9281"]]},{"id":"c1aec982.63b988","type":"function","z":"77db09d1.403ba8","name":"","func":"flow.set('humi', msg.payload.humi)\nflow.set('temp', msg.payload.temp)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":490,"y":4660,"wires":[[]]},{"id":"46e11606.fcc408","type":"http in","z":"77db09d1.403ba8","name":"","url":"/sensor","method":"get","upload":false,"swaggerDoc":"","x":170,"y":4720,"wires":[["66aa5722.6b53f8"]]},{"id":"66aa5722.6b53f8","type":"function","z":"77db09d1.403ba8","name":"","func":"let humi = flow.get('humi') || 0\nlet temp = flow.get('temp') || 0\nmsg.payload = {\n    humi, temp\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":4720,"wires":[["c24d1af.43c51e8"]]},{"id":"c24d1af.43c51e8","type":"http response","z":"77db09d1.403ba8","name":"","statusCode":"","headers":{},"x":490,"y":4720,"wires":[]},{"id":"16b09f20.3b9281","type":"json","z":"77db09d1.403ba8","name":"","property":"payload","action":"","pretty":false,"x":330,"y":4660,"wires":[["c1aec982.63b988"]]},{"id":"c97be055.a659d","type":"mqtt-broker","name":"","broker":"www.carwasher.com.cn","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

Global

与前两种类似, Global是解决跨流数据共享的. 在函数节点中主要是以下两个API

let bar = global.get('foo') || 0 //有则获取, 无则为0
global.set('foo', 'bar') // 将foo写入值'bar'

除了在函数节点中通过代码的方式使用Context, 也可以在inject节点, change节点等节点中使用.

Node-RED编程基础

Node-RED编程基础

Node-RED的上下文Context, 为我们的编程提供了很大的便利, 它是实现复杂应用必不可少的一部分, 就如同其它编程语言中的局部变量/全局变量, 少了这个特性, 许许多多的功能几乎实现不了.

函数节点function

在Node-RED中, 很少使用代码, 所以要写代码的地方就成了比较困难的一部分. 函数节点使用JavaScript编程, 支持大部分API, 上面有穿插的使用, 但并不系统, 下面就对这个节点进行一个较为系统的梳理. 官方文档中也有很细致的说明, 喜欢看官方文档的可以直接参考.

消息是通过msg对象进行传递的, 通常会有一个payload的键值对包含消息的主体, 其他节点会msg对象上添加新的键值对.

上文提到, 直接将msg返回, 不做任何处理. 同时这个对象并无强制命名.

return msg;
// 以下等价.
// let message = msg;
// return message; 

如果返回null, 则停止传递.

return null;
// 以下等价.
// return ; 

并且, 函数节点必须返回一个对象或者null, 如果返回字符串/数字等, 会产生一个错误.

多端口输出

我们可以看到, 函数节点是可以设置多输出的, 此时返回的对象需要是一个与输出数相同长度的数组. 输出端口数也可以通过node.outputCount获取

Node-RED编程基础

返回的数组按序依次从对应的端口输出.例如:

if (msg.topic === "banana") {
   return [ null, msg ];
} else {
   return [ msg, null ];
}

如果msg.topicbanana 则从2号口输出, 非banana则从1号口输出

异步发送消息

通常我们使用节点发送消息都是同步的, 何为同步呢? 这是一个比较直观的概念, 单向一车道堵车了, 你只能同步的等待, 前面不走我们就没办法走, 这也许损耗了极大的性能. 而现在应用更广的是异步模式, 我们可以不用等待处理结果, 处理结束了通知我即可, 就像你安排别人做个事情, 安排完了, 就去忙别的事了, 他做好事情再来通知你. 例如:

setTimeout(()=>{
    msg.payload = 'notify'
    node.send(msg)
  	node.done()
}, 1000)
return;

我们使用setTimeout出启动一个延时任务, 消息不直接返回, 在1000ms后通过node.send返回.

同时, 我们还经常遇到一个非常常见的需求, 我们需要将一个数组的内容配合MySQL节点插入到数据库中, 我们就可以使用node.send来实现这个功能.

data = [25.0, 25.3, 25.1, 25.4, 25.6]

data.forEach((item)=>{
    sql = `insert into sensors (temp) values (${item}) `
    msg.topic = sql
    node.send(msg)
})

return ;

执行结果:

Node-RED编程基础

在异步任务中, 还有一个较为重要的概念则是回调, 回调即是返回调用, 别人干完事了回来通知. 但别人通知总需要一个入口, 这个入口称之为event, 对event的处理成为event handler 或者callback, 此处并不严谨, 仅供理解. 例如, 我们在使用Context存储数据的时候, 如果其存储在文件系统上, IO操作要慢许多, 如果使用同步的方式获取, 会极大地影响性能, 此时我们就会通过异步的方式获取. 实现如下:

flow.get(['humi', 'temp'], (err, humi, temp) => { // 获取多个context
    if(err) return 
    node.send({
        payload: {
            humi: humi || 0,
            temp: temp || 0
        }
    })
    node.done()
})
return ;

其中的arrow function就是一个回调函数.

节点状态

Node-RED也提供了状态显示的API, 例如调用

node.status({fill:"green",shape:"dot",text:"完成"});

就会出现如下效果:

Node-RED编程基础

具体的API可以参考官方文档

使用外部模块

[注] 需要Node-RED版本>=1.3.0

当我们遇到一些需求需要使用别人造好的轮子时, 我们就不得不使用外部模块. 函数节点也提供了该功能. 首先需要去.node-red文件夹下找到settings.js文件, 如果不知道该文件在哪里, 可以从启动日志找到, 如下:

Node-RED编程基础

在文件中添加functionExternalModules: true, 如图:

Node-RED编程基础

此时启动Node-RED, 双击函数节点, 进入Setup就可以看到如下画面:

Node-RED编程基础

你可以通过左下角添加按钮, 添加需要使用的模块, 第三方模块就会被自动安装到.node-red/externalModules/中. 以一个小例子结束本部分内容: 有时我们需要获取网卡信息, 很多人都通过安装第三方节点实现, 但其实, 并不需要第三方节点就可以实现.

我们引入了os模块, os模块提供了networkInterfacesAPI, 我们可以通过该模块获取网卡信息.

en0 = os.networkInterfaces().en0
ipv4 = en0[1] // en0[0]为ipv6, 需要根据自身环境修改
ip = ipv4.address
mac = ipv4.mac
msg.payload = {
    ip, mac
}
return msg;

执行结果如下:

Node-RED编程基础

有了这个feature后, Node-RED的功能得到了极大的增强, 举个例子, 我们可以通过引入johnny-five, 通过函数节点直接对硬件进行编程. 等等.

如果需要全局引入某个模块可以通过修改functionGlobalContext实现.

例如, 我们同样在settings.js中引入os模块, 重启Node-RED, 我们就不需要再函数节点的setup中引入os, 仅需要在函数中通过os = global.get('os')引入即可.

事件记录

在函数节点中可以使用node.log/node.warn / node.error 记录某些事件, 方便调试.

期待与您成为朋友文章来源地址https://www.toymoban.com/news/detail-409035.html

到了这里,关于Node-RED编程基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • node-red - 读写操作redis

    安装配置node-red环境: centos通过源文件的方式安装node-red nodered-环境搭建及使用 安装配置redis: centos - docker安装redis Windows10安装redis(图文教程) Redis支持的数据结构 回到目录 1.在node-red里面安装redis节点 : 2. 刷新node-red: 回到目录 3.1.1 List(列表)存储 :redis-out节点   redis

    2024年02月10日
    浏览(39)
  • 如何使用 Docker 安装 Node-RED

    安装 Node-RED 使用 Docker 是一种简便的方式,以下是基本的步骤: 安装 Docker: 确保已在系统上安装 Docker。可从 Docker 官方网站 或 Windows Docker 安装教程 获取安装指南。 拉取运行 Node-RED 镜像: 打开终端或命令行界面,运行以下命令安装 Node-RED。您可以使用官方的 nodered/node-r

    2024年04月22日
    浏览(48)
  • Node-Red中Homeassistant节点使用

    谷歌解释:Home Assistant is an open-source home automation platform that focuses on privacy and local control. 是一个开源的家庭自动化控制管理平台。 Homeassistant简称HA,目前我们想要远程控制家里的电器等设备,首先需要购买智能家居,而智能家居市场上存在许多家居生态(米家、天猫、homeki

    2024年02月09日
    浏览(42)
  • node-red安全部署方式-安全登录功能

      安装号的node-red,默认是没有用户登陆功能的,每次进入工作界面只需输入 服务器ip:端口号 即可登陆。但是假如其他人知道了我们的ip地址,岂不是任何人都可以访问我们的服务器呢?基于这种情况,我们需要给node-red添加安全认证,即安全登陆功能,使得每次进入node

    2024年02月15日
    浏览(46)
  • 在nodejs应用中集成node-red

    随着物联网(IoT)和边缘计算的快速发展,实时数据处理和可视化变得越来越重要。Node-RED是一个基于JavaScript的开源平台,用于创建实时数据流应用程序。它提供了一个可视化的开发环境,使用户可以轻松地构建、部署和管理数据流。本文将介绍如何在Node.js应用中集成Node-RED,以

    2024年02月14日
    浏览(47)
  • 【Node-RED】安全登陆时,账号密码设置

    Node-RED 在初始下载完成时,登录是无账号密码的。基于安全性考虑,本期博文介绍 在安全登陆时,如何进行账号密码设置 。当然,此处可以参考官方使用指南Securing Node-RED,里面有更为详细的介绍。 而本博文只对用到的进行日志记录,方便后续回顾查看 。 在使用指南中,对

    2024年02月19日
    浏览(39)
  • Node-Red与ModbusTCP设备通信——读数据

    一、内容简介 本篇内容主要介绍Node-Red通过node-red-contrib-modbus插件与ModbusTCP设备进行通讯,这里用Modbus Slave工具来模拟从站设备,Node-Red作为主站分别从0地址开始读取10个线圈状态和10个保持寄存器,分别用Modbus-Read、Modbus-Getter、Modbus-Flex-Getter三个节点以不同的方式来实现。

    2024年01月24日
    浏览(52)
  • Node-RED与uibuilder构建自定义UI

    Node-RED是一款可以进行可视化编程的低代码工具, 在快速构建原型和做小型应用有着较大优势. 在Node-RED中构建图形化(GUI)界面通常使用Dashboard完成, 其UI简约好看, 但其界面无法自定义, 只能使用现有的节点组件, 对于特殊界面无法满足. 因此Node-RED社区推出了uibuilder. 其可以使用

    2024年01月17日
    浏览(55)
  • centos通过源文件的方式安装node-red

    [回到目录]  查看你的Linux系统是32位还是64位的,不要搞错版本了。执行命令: cat /proc/version  下载地址:【https://npm.taobao.org/mirrors/node/】  选择合适的版本下载: 记住查看你的Linux系统是32位还是64位的,不要搞错版本了。一般x86_64是64位,x86是32位的。 我的服务器是64位的

    2024年02月11日
    浏览(37)
  • Node-Red-访客、操作员和管理员登录

    要实现Node-Red识别图片内容,在这里我们需要下载安装有控件: node-red-dashboard 。 首先在左上角点击设置,并找到节点管理 ; 在节点管理中点击安装; 在安装界面的查询窗口输入node-red-dashboard控件,查询后选择下载,等待下载完成; 本案例主要实现的功能包含有模式选择及

    2023年04月08日
    浏览(79)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包