2024/10分享第一篇Telegram開始到現在已經過去很久也改版過很多次
今天將目前能用的設定方式統一整合起來
一 安裝需要的整合以及服務
1.1 安裝通知軟體
Synology Chat設定方式請參考下方連結
[分享] Synology Chat設定
取得Telgram相關ID請參考下列之前的分享文章
[分享]Telegram 機器人創建token ID 以及群組創建ID 取得方法
因之前改版已經取消yaml設定方式
所以上面的舊文章只要創建好Telegram並取得Token以及ID即可
或者直接看下面內容是目前版本的設定方式
到系統 整合 搜尋Telegram
進去後選擇Telegram bot
依照內容先到botfather去新增機器人
便可以取得api token
輸入後便可以按傳送創建
沒問題的話就可以看到新建好的機器人了
至於怎麼創建群組跟取得群組ID請參考舊文章
再來就可以新增群組的ID
直接新增允許的聊天室ID
你創建好的機器人都會列出 選你的群組是屬於哪個機器人
我這邊沒有創群組所以是直接丟給機器人用的就是機器人的ID
也可以依照說明取得chat_id
注意 跟機器人的聊天ID是正數 如果是群組的會是負數
輸入後傳送即可
便可新增完成
可以看到群組或者是直接跟機器人聊天的ID是有差別的
在使用上要特別注意
1.2 安裝TTS軟體
因我都是用Edge 所以下面都是用Edge TTS來說明
Edge安裝可以參考我之前寫的舊文
Edge TTS Node-Red 亂數語音+亂數訊息分享
裝完這些就可以開始來設定了
如果都已經安裝可以直接跳過
二 NodeRed設定
因前段時間Telegram配合HA的更新改版一直在改發送的格式
相信各位應該都有收到通知
而我之前發放通知Flow都是個別處理導致要改的地方會一大堆
現在把格式統一整合到2個Function來處理
第1個Function負責處理要傳送格式
看是要傳送純文字,還是圖片, 還有TTS是否播放, 正常音量設定, 夜間時段音量設定。
第2個處理要傳送的格式內容
前Function 內容
請依照格式設定好相關內容
// ===== 0. Speaker 清單 =====
// 格式:entity_id / 白天音量 / 深夜音量
// 如果有多顆直接複製貼上修改 Speaker? 增加上去
//var Speaker? = {
// entity_id: "實體ID", // 喇叭位置
// normal_vol: 0.7,
// nite_vol: 0.3
//};
// 自動組合 AllSpeakers
// 依照你的喇叭數量添加修改
var SpeakerMap = {
Speaker1,
// Speaker2,
// Speaker3,
// Speaker4,
// Speaker5
};
// 此段不需動
var AllSpeakers = Object.values(SpeakerMap).filter(s =>
s &&
typeof s.entity_id === "string" &&
s.entity_id.trim() !== ""
);
// ===== 0-1. Telegram 設定 =====
// 沒填實體資料為空有多組照格式加上即可
var Telegram1 = "notify.telegram_bot_你的實體ID";
var Telegram2 = "";
var Telegram3 = "";
// 判斷喇叭數量不需動
var Telegram_Entity_List = [Telegram1, Telegram2, Telegram3]
.filter(v => typeof v === "string" && v.trim() !== "");
// ===== 0-2. 深夜時段設定 =====
// 例如 23:00 ~ 06:59 算深夜
var night_start_hour = 23;
var night_end_hour = 7;
// ===== 1. 設定抓取時間格式 =====
const now = new Date();
const pad = (num, len = 2) => num.toString().padStart(len, "0");
// date: yyyy-mm-dd_HH_MM_SS
const date = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}_${pad(now.getHours())}_${pad(now.getMinutes())}_${pad(now.getSeconds())}`;
// date2: yyyy/mm/dd HH:MM:SS
const date2 = `${now.getFullYear()}/${pad(now.getMonth() + 1)}/${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
// ===== 2. 隨機訊息內容 =====
var myArray = [
//純文字訊息使用下方格式
// "純文字訊息1",
// "純文字訊息2"
// 傳送的文字如果需要帶日期格式改用下列方式
// `${date2}\n宿舍攝影機偵測到移動!`
];
var randomItem = myArray[Math.floor(Math.random() * myArray.length)];
// ===== 3. 隨機 TTS 語音 =====
var myVoice = [
//個人覺得edge tts好聽的語音,可依照自己喜好修改
"zh-TW-HsiaoChenNeural",
"zh-CN-XiaoxiaoNeural"
];
var randomVoice = myVoice[Math.floor(Math.random() * myVoice.length)];
// ===== 4. 這次通知設定 =====
var image_send = "no"; // 傳送照片 yes / no
var tts_send = "no"; // 使用TTS yes / no
// ===== 5. 圖片資料 =====
// 要用圖片就直接填完整路徑與網址
// 不用就留空字串
// var image_path = "";
// var image_url = "";
var image_path = `/config/www/image/snapshot_${date}.jpg`;
var image_url = `http://你的HAip:8123/local/image/snapshot_${date}.jpg`;
// ===== 6. TTS 設定 =====
// on = 全時 normal 音量
// nite = 深夜使用 nite_vol
// off = 深夜不播
var tts_night_mode = "on";
// tts_message 可和 message 不同
var tts_message = randomItem;
// 這裡可自由指定喇叭
// 全部播放:AllSpeakers
// 單顆播放:[Speaker1]
// 多顆指定:[Speaker1, Speaker2]
var tts_speakers = AllSpeakers;
// ===== 7. 若需要圖片,提供給 camera.snapshot / 舊流程相容用 =====
if (image_send === "yes" && image_path !== "") {
msg.payload_snapshot = {
filename: image_path
};
}
// ===== 8. 統一輸出 notify 物件 =====
msg.notify = {
message: randomItem,
telegram_entity_list: Telegram_Entity_List,
image_send: image_send,
image_path: image_path,
image_url: image_url,
tts_send: tts_send,
tts_voice: (tts_send === "yes") ? randomVoice : "",
tts_speakers: (tts_send === "yes") ? tts_speakers : [],
tts_night_mode: tts_night_mode,
tts_message: (tts_send === "yes") ? tts_message : "",
night_start_hour: night_start_hour,
night_end_hour: night_end_hour
};
return msg;
後Function內容
// ===== 1. 讀取前面 Function 傳來的 notify 物件 =====
const notify = msg.notify || {};
const message = notify.message || "";
const telegram_entity_list = Array.isArray(notify.telegram_entity_list)
? notify.telegram_entity_list.filter(v => typeof v === "string" && v.trim() !== "")
: [];
const image_send = notify.image_send || "no";
const image_path = notify.image_path || "";
const image_url = notify.image_url || "";
const tts_send = notify.tts_send || "no";
const tts_voice = notify.tts_voice || "";
const tts_speakers = Array.isArray(notify.tts_speakers) ? notify.tts_speakers : [];
const tts_night_mode = notify.tts_night_mode || "on";
const tts_message = notify.tts_message || message;
const night_start_hour = Number(notify.night_start_hour ?? 23);
const night_end_hour = Number(notify.night_end_hour ?? 7);
// ===== 2. 準備 5 個輸出 =====
let msg_telegram_photo = null;
let msg_telegram_text = null;
let msg_synology_chat = null;
let msg_set_volume = null;
let msg_tts = null;
// ===== 3. Telegram =====
// 多組 Telegram 會用 push 方式逐筆送出
if (telegram_entity_list.length > 0) {
if (image_send === "yes" && image_path !== "") {
let telegramPhotoMsgs = [];
telegram_entity_list.forEach(id => {
telegramPhotoMsgs.push({
...msg,
payload_telegram_photo: {
entity_id: id,
file: image_path,
caption: message
}
});
});
if (telegramPhotoMsgs.length > 0) {
msg_telegram_photo = telegramPhotoMsgs;
}
} else {
let telegramTextMsgs = [];
telegram_entity_list.forEach(id => {
telegramTextMsgs.push({
...msg,
payload_telegram_text: {
entity_id: id,
message: message
}
});
});
if (telegramTextMsgs.length > 0) {
msg_telegram_text = telegramTextMsgs;
}
}
}
// ===== 4. Synology Chat =====
if (image_send === "yes" && image_url !== "") {
msg_synology_chat = {
...msg,
payload_synology_chat: {
data: {
file_url: image_url
},
message: message.replace(/%/g, "%25").replace(/&/g, "%26")
}
};
} else {
msg_synology_chat = {
...msg,
payload_synology_chat: {
message: message
}
};
}
// ===== 5. TTS + 設定音量 =====
if (tts_send === "yes" && tts_speakers.length > 0) {
const now = new Date();
const hour = now.getHours();
let isNight = false;
if (night_start_hour > night_end_hour) {
// 例如 23 -> 7,跨日
isNight = (hour >= night_start_hour || hour < night_end_hour);
} else if (night_start_hour < night_end_hour) {
// 例如 1 -> 6,不跨日
isNight = (hour >= night_start_hour && hour < night_end_hour);
} else {
// 相同代表整天都算夜間,通常不會這樣設
isNight = true;
}
// off = 深夜不播
if (!(tts_night_mode === "off" && isNight)) {
// 5-1. 先產生多筆音量設定訊息
let volumeMsgs = [];
let ttsEntityList = [];
tts_speakers.forEach(sp => {
if (!sp || typeof sp.entity_id !== "string" || sp.entity_id.trim() === "") return;
ttsEntityList.push(sp.entity_id);
// 音量選擇邏輯
let finalVol = null;
if (isNight && tts_night_mode === "nite") {
finalVol = sp.nite_vol;
} else {
finalVol = sp.normal_vol;
}
if (finalVol !== "" && finalVol !== null && finalVol !== undefined) {
volumeMsgs.push({
...msg,
payload_setvol: {
entity_id: sp.entity_id,
volume_level: Number(finalVol)
}
});
}
});
if (volumeMsgs.length > 0) {
msg_set_volume = volumeMsgs;
}
// 5-2. 再產生 TTS 訊息(只會有一筆)
if (ttsEntityList.length > 0) {
msg_tts = {
...msg,
payload_tts: {
media_player_entity_id: ttsEntityList,
message: tts_message,
cache: true,
options: {
volume: "+100%",
voice: tts_voice !== "" ? tts_voice : "zh-TW-HsiaoChenNeural",
pitch: "+0Hz",
rate: "+0%"
}
}
};
}
}
}
// ===== 6. 回傳 5 個輸出 =====
// Output 1: Telegram Photo(多筆)
// Output 2: Telegram Text(多筆)
// Output 3: Synology Chat
// Output 4: 設定音量(多筆)
// Output 5: TTS(單筆)
return [msg_telegram_photo, msg_telegram_text, msg_synology_chat, msg_set_volume, msg_tts];
相關節點設定
後Function因為有5個Output 所以輸出需要改成5
傳送Telegram圖片
Action 用 telegram_bot.send_photo
data 用 msg.payload_telegram_photo
傳送Telegram文字訊息
Action 用 notify.send_message
data 用 msg.payload_telegram_text
傳送Synology chat通知
Action 用 notify.synology_chat_bot
data 用 msg.payload_synology_chat
設定音量
Action 用 media_player.volume_set
data 用 msg.payload_setvol
設定TTS
Action 用 tts.speak
Target 需要選擇 Edge TTS
data 用 msg.payload_tts
這邊需要注意的是TTS前面有加一個延遲
主要是因為要先設定音量再去播放TTS所以要注意自己喇叭數量修改延遲的時間
我5顆喇叭設定1s 沒遇到問題
如果你比我多顆那就要注意觀察是否會造成音量還沒改就先播放了
以上為這次分享
個人認為還不是很完整
下版我將會針對傳送訊息的部分做修改
應該會納入HA Notify
傳送訊息的部分是否啟用
比如
是否啟用 Telegram 通知
是否啟用 Synology Chat 通知
是否啟用 HA Notify 通知
或者你有想要加的功能也可以留言
可以的話我會盡量加進來
本次都是透過 ChatGPT 一步一步弄出來的



















