通知设置
通知设置
本节介绍如何设置 Node-RED 通知系统,当 ESP32-CAM 检测到运动并拍照后,自动通过 Telegram Bot 和 Email 发送通知。学习完成后,您将能够:
- 创建和配置 Telegram Bot
- 在 Node-RED 中集成 Telegram 通知节点
- 设置图片+文本的推送通知
- 配置 Email 通知作为备用通道
┌────────────────────────────────────────────────────────────┐│ 远程巡检通知系统 │├────────────────────────────────────────────────────────────┤│ ││ [ESP32-CAM 检测到运动 → 拍照] ││ │ ││ ▼ ││ [Node-RED] ││ │ ││ ├──→ [保存图片到服务器] ││ │ ││ ├──→ [Telegram Bot] ││ │ ├──→ 发送文本消息: "检测到运动!" ││ │ ├──→ 延迟 1 秒 ││ │ └──→ 发送图片文件 ││ │ ││ └──→ [Email 通知] ││ ├──→ 发送 HTML 格式邮件(包含嵌入式图片) ││ └──→ 抄送管理员 ││ │└────────────────────────────────────────────────────────────┘- 已完成 11-04. Photo Capture via MQTT
- 已完成 11-08. Node-RED Image Processing
- Telegram 账号(手机端)
- SMTP 邮箱账号(用于 Email 通知)
Step 1: Create a Telegram Bot
Section titled “Step 1: Create a Telegram Bot”通过 BotFather 创建 Bot
Section titled “通过 BotFather 创建 Bot”1. 打开 Telegram App2. 搜索 @BotFather → 点击 Start3. 发送: /newbot4. 输入 Bot 名称: "Factory Monitor Bot" (可自定义)5. 输入 Bot 用户名: "factory_monitor_bot" (必须以 bot 结尾)6. BotFather 返回 API Token: => 1234567890:ABCDefghIJKlmnopQRStuVWXyz1234567890
7. 可选: 自定义 Bot 头像和描述 /setuserpic → 上传 Bot 头像 /setdescription → 设置 Bot 描述
8. 保存 Token,后续 Node-RED 需要获取 Chat ID
Section titled “获取 Chat ID”1. 搜索你刚创建的 Bot 用户名 → 点击 Start2. Node-RED 将接收到包含 chat ID 的消息3. 发送任意消息到 Bot 以获取聊天 IDStep 2: Install Node-RED Telegram Nodes
Section titled “Step 2: Install Node-RED Telegram Nodes”# 通过 Palette 管理# Manage Palette → Install → "node-red-contrib-telegrambot"
# 或命令行docker exec -it nodered npm install node-red-contrib-telegrambotStep 3: Configure Telegram Bot in Node-RED
Section titled “Step 3: Configure Telegram Bot in Node-RED”添加 Telegram Bot 配置
Section titled “添加 Telegram Bot 配置”[Telegram Receiver] ──→ [Debug: 查看消息]
[Function: 构建通知] ──→ [Telegram Sender]Telegram Bot 配置节点:
| 参数 | 值 |
|---|---|
| Name | Factory Monitor Bot |
| Bot Token | 1234567890:ABCDefghIJKlmnopQRStuVWXyz1234567890 |
| Type | Bot |
获取 Chat ID 流程
Section titled “获取 Chat ID 流程”部署后向 Bot 发送任意消息,Telegram Receiver 节点将收到:
{ "payload": { "chatId": "987654321", "type": "message", "content": "/start", "from": { "id": 12345, "first_name": "User" } }}记录 Chat ID: 记录下
chatId值(例如 987654321),后续发送通知时使用。
Step 4: Build Notification Flow
Section titled “Step 4: Build Notification Flow”完整通知流程
Section titled “完整通知流程”[MQTT In: esp32cam/photo] │ ├──→ [Write File: 保存图片到 /data/esp32cam/] │ └──→ [Function: 发送 Telegram 文本] │ │ │ └──→ [Telegram Sender: 文本消息] │ ├──→ [Delay: 1 秒] │ └──→ [Function: 发送 Telegram 图片] │ └──→ [Telegram Sender: 图片]Function 节点 - 发送文本通知
Section titled “Function 节点 - 发送文本通知”// Function: 构建 Telegram 文本消息// 当收到新图片时,发送通知消息
// 从 Flow Context 获取聊天 IDvar chatId = flow.get("telegramChatId") || "987654321"; // 替换为实际 Chat ID
// 获取图片元数据var meta = flow.get("lastPhotoMeta") || {};
var message = { payload: { chatId: chatId, type: "message", content: "⚠️ *远程巡检告警*\n\n" + "📸 ESP32-CAM 检测到运动并已拍照\n" + "🕐 时间: " + new Date().toLocaleString() + "\n" + "📏 图片大小: " + (meta.size || "未知") + " 字节\n" + "🔢 唤醒次数: " + (meta.boot || "-") + "\n\n" + "请在 Node-RED Dashboard 查看完整画面。", parse_mode: "Markdown" // Markdown 格式 }};
return message;Function 节点 - 发送图片
Section titled “Function 节点 - 发送图片”// Function: 发送已保存的图片// 从服务器文件系统读取并发送
var chatId = flow.get("telegramChatId") || "987654321";var fs = require('fs');var path = "/data/esp32cam/latest.jpg";
// 方式 1: 发送服务器上的文件try { if (fs.existsSync(path)) { var photo = fs.readFileSync(path);
var message = { payload: { chatId: chatId, type: "photo", content: photo.toString('base64'), // Base64 编码的图片数据 filename: "surveillance_" + Date.now() + ".jpg" } }; return message; }} catch (e) { node.error("File read error: " + e.message);}
return null;Telegram Sender 节点配置
Section titled “Telegram Sender 节点配置”| 参数 | 值 |
|---|---|
| Bot | Factory Monitor Bot (选择已配置的 Bot) |
| Type | msg.payload (由 Function 节点动态指定) |
| Name | 发送通知 |
Step 5: Add Delay Between Messages
Section titled “Step 5: Add Delay Between Messages”Telegram 对频繁发送消息有限制,添加延迟节点:
[Function: 文本消息] ──→ [Delay: 1 秒] ──→ [Telegram Sender: 文本]
[Function: 图片消息] ──→ [Delay: 2 秒] ──→ [Telegram Sender: 图片]Delay 节点配置:
| 参数 | 值 |
|---|---|
| Action | Delay each message |
| Delay | 1-2 秒 |
| Rate | 1 message per 1 second |
Step 6: Email Notification (Alternative Channel)
Section titled “Step 6: Email Notification (Alternative Channel)”安装 Email 节点
Section titled “安装 Email 节点”# 通过 Palette 安装npm install node-red-node-emailSMTP 配置
Section titled “SMTP 配置”使用 Node-RED 的 Email 节点发送图片通知:
[MQTT In: esp32cam/photo] │ └──→ [Function: 构建邮件] │ └──→ [Email: 发送]Email 节点配置:
| 参数 | 值 |
|---|---|
| To | admin@factory.com |
| From | no-reply@factory-monitor.local |
| Server | smtp.gmail.com (或其他 SMTP) |
| Port | 465 (SSL) 或 587 (TLS) |
| Security | SSL/TLS |
| Authentication | ✅ 启用 |
| UserId | your-email@gmail.com |
| Password | 应用专用密码 |
Function 节点 - 构建 HTML 邮件
Section titled “Function 节点 - 构建 HTML 邮件”// Function: 构建带图片的 HTML 邮件// msg.payload 为二进制图片数据
// 图片编码为 Base64 嵌入 HTMLvar base64Image = msg.payload.toString('base64');
msg.payload = "";msg.topic = "📸 远程巡检告警 - " + new Date().toLocaleString();
msg.envelope = { to: "admin@factory.com", from: "no-reply@factory-monitor.local"};
msg.payload = `<!DOCTYPE html><html><head> <meta charset="UTF-8"> <style> body { font-family: Arial, sans-serif; } .header { background: #dc3545; color: white; padding: 15px; text-align: center; } .content { padding: 20px; } img { max-width: 100%; border: 1px solid #ddd; border-radius: 8px; } .footer { font-size: 12px; color: #666; margin-top: 20px; } </style></head><body> <div class="header"> <h2>⚠️ 远程巡检告警通知</h2> </div> <div class="content"> <p><strong>检测时间:</strong> ${new Date().toLocaleString()}</p> <p><strong>设备:</strong> ESP32-CAM (Factory Area A)</p> <p><strong>事件:</strong> PIR 运动传感器触发</p> <hr> <h3>📷 现场照片:</h3> <img src="cid:photo" alt="现场照片"> <hr> <p><a href="http://nodered.local:1880/ui">👉 查看完整 Dashboard</a></p> </div> <div class="footer"> <p>此邮件由工厂远程巡检系统自动发送</p> </div></body></html>`;
// 添加内联图片附件msg.payloadType = 'html';msg.attachments = [ { filename: 'photo.jpg', data: base64Image, encoding: 'base64', cid: 'photo' // Content-ID,用于 HTML 中引用 }];
return msg;# 1. 测试 Telegram Bot# 向 Bot 发送 /start,确认 Node-RED 接收# 输出: chatId: 987654321
# 2. 触发拍照并验证通知mosquitto_pub -t "esp32cam/command" -m "take_photo"
# 3. 验证 Telegram 是否收到# 手机端应收到:# ⚠️ 远程巡检告警# 📸 ESP32-CAM 检测到运动并已拍照# 🕐 时间: 5/18/2026, 14:30:25# 1秒后收到照片
# 4. 验证 Email 是否收到# 检查管理员邮箱Common Customer Questions
Section titled “Common Customer Questions”Q1: Telegram 通知能否推送到群组?
Section titled “Q1: Telegram 通知能否推送到群组?”可以。创建群组后将 Bot 添加到群组,然后在群组中发送 /start,获取群组的 Chat ID,使用该 ID 发送消息。
Q2: 如何防止夜间不必要通知?
Section titled “Q2: 如何防止夜间不必要通知?”在 Node-RED 中添加时间判断:
// Function: 时间过滤var hour = new Date().getHours();if (hour >= 22 || hour < 7) { // 夜间: 静默处理,仅记录不通知 msg.payload = null; return msg;}// 白天: 正常通知return msg;Q3: 如何配置多个通知接收人?
Section titled “Q3: 如何配置多个通知接收人?”// Function: 群发通知var recipients = [ "987654321", // 管理员 "876543210", // 值班工程师 "-123456789" // 群组 (负数表示群组)];
// 创建消息队列var messages = [];recipients.forEach(function(chatId) { messages.push({ payload: { chatId: chatId, type: "message", content: "⚠️ 远程巡检告警..." } });});
// 发送第一条消息,后续通过 Node-RED Loopreturn [messages[0]];✅ 推荐做法:
- Telegram 文本和图片分开发送,中间加 1-2 秒延迟
- 使用 Markdown 格式化消息增强可读性
- 图片保存到服务器后再发送(而非直接转发 MQTT 缓冲)
- 配置备用通知通道(Telegram + Email)
- 记录 Chat ID 到 Flow Context,避免硬编码
❌ 避免做法:
- 文本和图片合并为一条消息发送
- 频繁发送通知(建议同一事件 5 分钟内不重复推送)
- 未验证 Chat ID 是否正确就发送消息
- 将 Bot Token 硬编码在 Flow 中暴露
Summary
Section titled “Summary”- Telegram Bot 通过 BotFather 创建,获取 API Token
- node-red-contrib-telegrambot 提供 Receiver/Sender 节点
- 文本+图片分开发送,中间加 1-2 秒延迟
- Email 通知作为备用通道,支持 HTML 格式和嵌入式图片
- Chat ID 标识接收者,支持个人和群组推送