node-red轻应用

node-red-contrib-home-assistant-websocket #连接到 home assistant 
node-red-contrib-cheerio-function (html解析jquery)

node-red-contrib-moment (时间计算)

node-red-node-pi-gpio  (树莓派)
node-red-node-serialport  (串口)


node-red-contrib-modbus
node-red-contrib-ui-led

node-red-node-arduino  (firmata 通信)

node-red-contrib-socketcan

EMQX (mqtt服务端)(当了kv存储)

建议

  • 涉及串口-需要延迟模块

    • (限速6/s 涉及回路+10sm延迟)
    • 485有严重的,数据同时发送的问题(不如can)
  • 开机启动,最好有自检通过再运行。

    • 输入输出线 先启动会出现怪问题

firmata 协议 (全双工控制) web测试

http

http://192.168.0.123:1880/tget?a=1

http://192.168.0.123:1880/send-by-phone?msg=123 #发送消息

(http in)->(http response) 直接连接

发送消息

curl --location --request POST 'https://qyapi.weixin.qq.com/cgi-bin/gettoken?access_token=G-Jeb3W990OXhh9VDt48zUEJDpNZQkArPnAinGcC6wMusLEEJzzaOwOB0LUvZYC3qjVJh629FnUE53WKsFj-rExQpVXu-NM_ZqcFINuiRjvLuqLw6xR5pDS7ZCoQUlGefCmmXgJgyr1Onb4e6Mi8xKr6UaSGW6wt5mrQL5YGmvf1Xl-nG1HzIhK3MGkyBObag54_pkzfg995hR1zF3RhMA' \
--header 'Content-Type: application/json' \
--data-raw '{
"corpid": "ww9c0c7927b70a1368",
"corpsecret": "liSANMa-e1atIqLlKSIQKpsB1YaZ0HbLBiaHGednV_A"
}'
msg.url="https://qyapi.weixin.qq.com/cgi-bin/gettoken?access_token=G-Jeb3W990OXhh9VDt48zUEJDpNZQkArPnAinGcC6wMusLEEJzzaOwOB0LUvZYC3qjVJh629FnUE53WKsFj-rExQpVXu-NM_ZqcFINuiRjvLuqLw6xR5pDS7ZCoQUlGefCmmXgJgyr1Onb4e6Mi8xKr6UaSGW6wt5mrQL5YGmvf1Xl-nG1HzIhK3MGkyBObag54_pkzfg995hR1zF3RhMA"
msg.payload={
"corpid": "ww9c0c7927b70a1368",
"corpsecret": "liSANMa-e1atIqLlKSIQKpsB1YaZ0HbLBiaHGednV_A"
}
return msg;

模块时间戳问题

npm search moment
npm install moment

功能.函数设置.导入模块


const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const result = moment( Date.now(); )
//.add(8, 'hours')
.format('HH:mm:ss');
输入消息 = result +'\n'+ timeZone

变量

全局变量

代码函数中调用


保存: flow.set('authToken', new_token);
读取: let token = flow.get('authToken');
 

表达式访问

$flowContext("在家与否")  
$globalContext("authToken")

parseInt($flowContext("温度") )

payload == 主逻辑

myload == 自有逻辑

代码编程

时间

new Date().toLocaleString('zh-CN')

用 moment库
 moment().format('YYYYMMDD HH:mm:ss')
Switch (开关)   
Function (功能)   支持多输出 代替Switch分支
Change (修改变量)  payload中没有获取到值就会卡住

消息推送

// in  msg变量  out msg变量   处理完后 赋值给msg.payload
let 输入消息  = msg.payload
if (msg.topic){
    输入消息 = msg.topic +'\n' +输入消息
}
msg.payload=   {
    "msgtype": "text",
    "text": {
        "content": 输入消息
    }
}
return msg;

远程执行命令

依赖模块 ssh-exec

msg.payload = `
cat <<EOF   > /mnt/sp-ip.list 
${msg.payload}
EOF

exit

`
return msg;

注意: 最后需要换行回车 ,并exit退出

数据库

 

msg.query = ` INSERT INTO oqdb_it."pc上报" (
    "物理地址", 
    "主机名", 
    "内存使用", 
    "内存大小",
    处理器名称,
    处理器核数,
    处理器频率,
    来着用户,
    系统名称,
    系统版本,
    网卡ip,
    来源ip,
    运行时间,

    updated_at ,
    上报时间
)
VALUES (
    $addr,
    $name,
    $memP, 
    $memSize,
    $cpuName,
    $cpuCore,
    $cpuHz,
    $from,
    $sysName,
    $sysVer,
    $netIp,
    $fromIp,
    $runTime,
    $nowTime,
     $nowTime
 
)
ON CONFLICT ("物理地址")  
DO UPDATE SET 
    "主机名" = EXCLUDED."主机名",
    "内存使用" = EXCLUDED."内存使用",
    "内存大小" = EXCLUDED."内存大小",
    "处理器名称" = EXCLUDED."处理器名称",
    "处理器核数" = EXCLUDED."处理器核数",
    "处理器频率" = EXCLUDED."处理器频率",
     "来着用户" = EXCLUDED."来着用户",
    "系统名称" = EXCLUDED."系统名称",
    "系统版本" = EXCLUDED."系统版本",
     "网卡ip" = EXCLUDED."网卡ip",
    "来源ip" = EXCLUDED."来源ip",
    "运行时间" = EXCLUDED."运行时间",
    "updated_at" = EXCLUDED."updated_at",
     "上报时间" = EXCLUDED."上报时间"
    ;
`
msg.queryParameters = {
"addr": msg.payload.网卡地址,
"name": msg.payload.主机名,
"memP": msg.payload.内存使用,
"memSize" : msg.payload.内存大小,
    "cpuName": msg.payload.处理器名称,
"cpuCore": msg.payload.处理器核数,
"cpuHz": msg.payload.处理器频率,
    "from": msg.payload.来着用户,
    "sysName": msg.payload.系统名称,
    "sysVer": msg.payload.系统版本,
    "netIp": msg.payload.网卡IP ,
    "fromIp": msg.req.headers["x-real-ip"],
    "runTime": msg.payload.运行时间,
    "nowTime": moment().format('YYYY-MM-DD HH:mm:ss'),
    
}
return msg;

http解析

cheerio节点

// 收集所有链接到数组中
let links = [];
$("a").each(function () {
    links.push($(this).text());
});
links = Array.from(new Set(links)).sort();
// 将数组赋值给msg.payload
msg.payload = links.join('\n')
return msg; 

 

收集命令行

iftop -P -n -N -t -s 10 -L 20 | \
curl -X POST -H "Content-Type: text/plain" --data-binary @- \
http://192.168.14.144:1880/wrt/iftop
 cat /mnt/bak/视频-ip.txt  | \
curl -X POST -H "Content-Type: text/plain" --data-binary @- \
http://192.168.14.144:1880/ipset/table4

处理命令输出

function extractIPs(text) {
    //匹配ip
    const ipPattern = /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g;
    return text.match(ipPattern) || [];
}
// 使用示例
const text = msg.payload
const ips = extractIPs(text);
let publicIPs = [];
// 筛选
ips.forEach(ip => {
    // 跳过 192.168 开头的 IP
    if (ip.startsWith("192.168")) {
        return; // 相当于 continue
    }
    // 处理其他 IP
    publicIPs.push(ip);
});
//--返回
msg.payload = publicIPs.join('\n')
return msg;

hass连接

用户 ->标签:安全->长期访问令牌



(url最后不能有/斜杠,协议+IP+端口)

打包模块

可以通过打包 废弃一部分初始数据

join模块 可以统一一次性更新

api

可以访问几乎所有的东西


Emoji

gpiod

gpiodetect
gpioinfo gpiochip0


/dev/ch343_iodev

安装CA证书

apk update && apk add ca-certificates