LHB阿好伯, 2024/10/22
Image Not Showing Possible ReasonsLearn More →
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Ntfy 是一個簡單但功能強大的發布-訂閱(pub-sub)通知服務
通過 HTTP PUT/POST 請求發送通知到任何設備
這是一個自託管的替代方案
可以取代 Line Notify 等服務
使用上若是無自己架設的需求
使用官方伺服器路徑https://ntfy.sh/ 即可
想一個不容易被猜到的topic(訊息主題)即可開始享用
其實跟MQTT很像
只是應用的方向不太一樣
有配套的APP使用上是能取代Line Notify
電腦端
手機端
[
{
"id": "c956e688cc74ad8e",
"type": "http request",
"z": "fabdd7a3.4045a",
"name": "ntfy.sh",
"method": "POST",
"ret": "txt",
"paytoqs": "ignore",
"url": "https://ntfy.sh/mytopic",
"tls": "",
"persist": false,
"proxy": "",
"authType": "",
"senderr": false,
"credentials":
{
"user": "",
"password": ""
},
"x": 590,
"y": 3160,
"wires":
[
[]
]
},
{
"id": "32ee1eade51fae50",
"type": "function",
"z": "fabdd7a3.4045a",
"name": "data",
"func": "msg.payload = \"Something happened\";\nmsg.headers = {};\nmsg.headers['tags'] = 'house';\nmsg.headers['X-Title'] = 'Home Assistant';\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 470,
"y": 3160,
"wires":
[
[
"c956e688cc74ad8e"
]
]
},
{
"id": "b287e59cd2311815",
"type": "inject",
"z": "fabdd7a3.4045a",
"name": "Manual start",
"props":
[
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": "20",
"topic": "",
"payload": "",
"payloadType": "date",
"x": 330,
"y": 3160,
"wires":
[
[
"32ee1eade51fae50"
]
]
}
]
// 使用 Base64 編碼中文標題
function encodeHeaderAsRFC2047(text) {
// 轉換成 Base64
const base64 = Buffer.from(text).toString('base64');
return `=?UTF-8?B?${base64}?=`;
}
msg.payload = `測站: ${msg.payload.測站}
⏰ 時間: ${msg.payload.時間}
📊 偵測值: ${msg.payload.偵測值}
⚠️ 預警值: ${msg.payload.預警值}
`;
msg.headers = {};
msg.headers['tags'] = 'rotating_light'; // 加入警告和警報 emoji
msg.headers['X-Title'] = encodeHeaderAsRFC2047('監測警報');
msg.headers['Priority'] = 5; // 設定最高優先級 (5 = max/urgent)
return msg;
結合到HA也十分方便
notify:
- name: ntfy
platform: rest
method: POST_JSON
data:
topic: YOUR_NTFY_TOPIC
title_param_name: title
message_param_name: message
resource: https://ntfy.sh
主要是可以辦帳號用於保存相關的資料
最後最重要一點
Ntfy 是以 Apache 許可證 2.0 和 GPLv2 許可證下獲得雙重許可發布的開源軟體
Apache License 2.0 主要特點:
完全允許商業使用:
主要要求:
商業應用場景:
授權相容性:
Line Notify替代方案 - discord| Telegram Bot 以Node-Red 進行測試
##創建緩存目錄:
sudo mkdir -p /var/cache/ntfy/attachments
sudo chown ntfy:ntfy /var/cache/ntfy/attachments
sudo nano /etc/ntfy/server.yml
添加以下內容:
base-url: "http://localhost:8080"
# 將 base-url 改為外部可訪問的 URL
#base-url: "URL"
attachment-cache-dir: "/var/cache/ntfy/attachments"
attachment-file-size-limit: "15M"
attachment-total-size-limit: "5G"
attachment-expiry-duration: "3h"
# 預設存取控制
auth-default-access: "read-write"
# 如果使用了 Cloudflare,建議添加以下設定
behind-proxy: true
設定正確的權限:
sudo chown ntfy:ntfy /etc/ntfy/server.yml
sudo chmod 644 /etc/ntfy/server.yml
重啟服務:
sudo systemctl restart ntfy
確認服務狀態:
sudo systemctl status ntfy
# 創建配置文件
sudo nano /etc/ntfy/server.yml
# 添加以下內容
base-url: "http://localhost:8080"
listen-http: ":8080"
log-level: info
log-file: /var/log/ntfy.log
enable-metrics: true
metrics-listen-http: ":9090"
# 創建所需目錄和設置權限
sudo mkdir -p /var/log/ntfy
sudo mkdir -p /var/cache/ntfy
sudo useradd -r -s /bin/false ntfy
sudo chown -R ntfy:ntfy /var/log/ntfy
sudo chown -R ntfy:ntfy /var/cache/ntfy
sudo chown -R ntfy:ntfy /etc/ntfy
# 重啟 ntfy 服務
sudo systemctl restart ntfy
# 安裝 Prometheus
sudo apt update
sudo apt install prometheus
# 配置 Prometheus
sudo nano /etc/prometheus/prometheus.yml
# 添加以下配置
global:
scrape_interval: 15s
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9091"]
- job_name: "ntfy"
static_configs:
- targets: ["localhost:9090"]
# 修改啟動配置
sudo nano /etc/default/prometheus
ARGS="--web.listen-address=:9091"
# 設置權限
sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml
sudo chmod 644 /etc/prometheus/prometheus.yml
# 重啟 Prometheus
sudo systemctl restart prometheus
# 添加 Grafana GPG 密鑰
sudo apt-get install -y software-properties-common wget
sudo wget -q -O /usr/share/keyrings/grafana.key https://packages.grafana.com/gpg.key
# 添加 Grafana 倉庫
echo "deb [signed-by=/usr/share/keyrings/grafana.key] https://packages.grafana.com/oss/deb stable main" | sudo tee -a /etc/apt/sources.list.d/grafana.list
# 更新並安裝 Grafana
sudo apt-get update
sudo apt-get install grafana
# 啟動 Grafana
sudo systemctl enable grafana-server
sudo systemctl start grafana-server
Note
import requests
import os
from pathlib import Path
import mimetypes
def get_mime_type(file_path):
"""
取得檔案的 MIME 類型
"""
mime_type, _ = mimetypes.guess_type(file_path)
return mime_type or 'application/octet-stream'
def send_to_ntfy(server_url, topic, message=None, image_path=None):
"""
發送訊息和圖片到NTFY服務器
參數:
server_url (str): NTFY服務器的URL (不包含結尾的斜線)
topic (str): NTFY的主題名稱
message (str, optional): 要發送的文字訊息
image_path (str, optional): 圖片檔案的路徑
"""
# 確保 server_url 不以斜線結尾
server_url = server_url.rstrip('/')
# 構建完整的URL
full_url = f"{server_url}/{topic}"
try:
# 如果有文字訊息要發送
if message:
response = requests.post(
full_url,
data=message.encode('utf-8'),
headers={"Content-Type": "text/plain"}
)
print(f"訊息發送狀態碼: {response.status_code}")
print(f"訊息發送回應: {response.text}")
if response.status_code != 200:
print(f"發送訊息失敗: {response.status_code}")
return False
# 如果有圖片要發送
if image_path and os.path.exists(image_path):
# 檢查檔案是否存在
if not os.path.exists(image_path):
print(f"找不到檔案: {image_path}")
return False
# 取得檔案大小
file_size = os.path.getsize(image_path)
print(f"檔案大小: {file_size} bytes")
# 取得檔案的 MIME 類型
content_type = get_mime_type(image_path)
print(f"檔案類型: {content_type}")
with open(image_path, 'rb') as image_file:
filename = Path(image_path).name
headers = {
"Filename": filename,
"Content-Type": content_type,
# 避免使用中文標頭
"Title": "Image Upload",
"Tags": "upload,image"
}
print(f"發送請求到: {full_url}")
print(f"使用標頭: {headers}")
response = requests.put(
full_url,
data=image_file,
headers=headers
)
print(f"圖片發送狀態碼: {response.status_code}")
if response.text:
print(f"圖片發送回應: {response.text}")
if response.status_code != 200:
print(f"發送圖片失敗: {response.status_code}")
return False
return True
except Exception as e:
print(f"發送過程中發生錯誤: {str(e)}")
return False
# 使用範例
if __name__ == "__main__":
# 設定參數
SERVER_URL = "http://localhost:8080" # 不要在結尾加斜線
TOPIC = "FTIR_OCR"
MESSAGE = "這是一個測試訊息"
IMAGE_PATH = "/home/huan-yu/processed_image.png"
# 發送訊息和圖片
success = send_to_ntfy(
server_url=SERVER_URL,
topic=TOPIC,
message=MESSAGE,
image_path=IMAGE_PATH
)
if success:
print("訊息和圖片發送成功!")
else:
print("發送失敗,請檢查錯誤訊息。")
查看網路上討論上也有許多人發生一樣的問題
https://github.com/binwiederhier/ntfy/issues/880
https://github.com/binwiederhier/ntfy/issues/1191
https://docs.ntfy.sh/config/#web-push
目前最佳的解決方案為使用PWA
需求條件
# 產生 VAPID 金鑰
sudo ntfy webpush keys
# 編輯設定檔
sudo nano /etc/ntfy/server.yml
# 重啟服務
sudo systemctl restart ntfy
server.yml中增加以下資訊
web-push-public-key: [公鑰]
web-push-private-key: [私鑰]
web-push-file: /var/cache/ntfy/webpush.db
web-push-email-address: [管理員郵箱]
🌟全文可以至下方連結觀看或是補充
全文分享至
https://www.facebook.com/LHB0222/
https://www.instagram.com/ahb0222/
有疑問想討論的都歡迎於下方留言
喜歡的幫我分享給所有的朋友 \o/
有所錯誤歡迎指教