--- disqus: ahb0222 GA : G-VF9ZT413CG --- > [color=#40f1ef][name=LHB阿好伯, 2024/10/22][:earth_africa:](https://www.facebook.com/LHB0222/) [TOC] ![image](https://hackmd.io/_uploads/HkzcegpSkl.png) # Ntfy介紹 Ntfy 是一個簡單但功能強大的發布-訂閱(pub-sub)通知服務 通過 HTTP PUT/POST 請求發送通知到任何設備 這是一個自託管的替代方案 可以取代 Line Notify 等服務 ## 主要特點: - ### 通知方式多元化: - 手機推播通知(Android / iOS) - 電子郵件通知 - WebSocket 即時通知 - Webhook 整合 - ### 多種格式支援: - 純文字訊息 - 結構化 JSON 資料 - 附加檔案傳輸 - 支援 Markdown 格式 - ### 安全性功能: - 訪問控制與身份驗證 - 端到端加密 - 即時訊息傳遞確認 - 支援 HTTPS 加密傳輸 - ### 整合能力: - REST API 支援 - 命令列工具 - 支援 Docker 部署 - 提供各種程式語言的套件(python/Go/PHP/C#/.NET/R/JS/Java/Node) # Ntfy 相較於 Line Notify 的優點: * 開源且可自行架設 * 支援多種通知方式 * 彈性的訂閱方案 * 具備檔案傳輸功能 * API 介面完整 * 不需要辦理帳號即可使用 使用上若是無自己架設的需求 使用官方伺服器路徑**https://ntfy.sh/** 即可 想一個不容易被猜到的topic(訊息主題)即可開始享用 其實跟MQTT很像 只是應用的方向不太一樣 有配套的APP使用上是能取代Line Notify - 電腦端 - https://ntfy.sh/app ![image](https://hackmd.io/_uploads/rkTglgTByl.png) - 手機端 - 安卓 [![image](https://hackmd.io/_uploads/BJwwPgprJe.png) ](https://play.google.com/store/apps/details?id=io.heckel.ntfy) - 蘋果 [![image](https://hackmd.io/_uploads/S1uIDeaSkl.png) ](https://apps.apple.com/us/app/ntfy/id1625396347) ![image](https://hackmd.io/_uploads/r1Y7gl6S1x.png) # 結合Node-Red ![image](https://hackmd.io/_uploads/BJ1Qke6Byg.png) ```json= [ { "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" ] ] } ] ``` ```javascript= // 使用 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; ``` # Home Assistant 結合到HA也十分方便 ```yaml= 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 ``` # 收費方案 主要是可以辦帳號用於保存相關的資料 ![image](https://hackmd.io/_uploads/ry7jsyaryg.png) # 是否可以商用? 最後最重要一點 Ntfy 是以 Apache 許可證 2.0 和 GPLv2 許可證下獲得雙重許可發布的開源軟體 Apache License 2.0 主要特點: * 完全允許商業使用: * 可以免費用於商業目的 * 可以修改原始碼 * 可以自由分發 * 可以私有使用 * 主要要求: * 必須保留原始版權聲明 * 必須包含 Apache License 的副本 * 若修改了代碼,需要明確說明 * 商業應用場景: * 企業內部部署 * 整合到商業產品中 * 提供託管服務 * 二次開發後商用 * 授權相容性: * 與大多數開源授權相容 * 可以與專有軟體結合 * 可以改變授權條款 # 相關文章 [Line Notify替代方案 - discord| Telegram Bot 以Node-Red 進行測試](/1j54odKDTvit8O3q5TktUw) # 自架伺服器啟用文件發送 ##創建緩存目錄: ``` 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 ``` ## 啟動監測 ### 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 安裝和配置 ``` # 安裝 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 安裝和配置 ``` # 添加 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] >Grafana配置檔 >https://raw.githubusercontent.com/binwiederhier/ntfy/main/examples/grafana-dashboard/ntfy-grafana.json ![image](https://hackmd.io/_uploads/r1uib7AvJg.png) # python使用範例 ```python= 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("發送失敗,請檢查錯誤訊息。") ``` # 問題排除 ## IOS 無法進行警訊通知 查看網路上討論上也有許多人發生一樣的問題 https://github.com/binwiederhier/ntfy/issues/880 https://github.com/binwiederhier/ntfy/issues/1191 https://docs.ntfy.sh/config/#web-push 目前最佳的解決方案為使用PWA :::success 需求條件 * 有效的 HTTPS 憑證 * 需設定 VAPID 金鑰對 * 資料庫儲存訪客訂閱資訊 * 管理員郵箱 ::: ```bash= # 產生 VAPID 金鑰 sudo ntfy webpush keys # 編輯設定檔 sudo nano /etc/ntfy/server.yml # 重啟服務 sudo systemctl restart ntfy ``` server.yml中增加以下資訊 :::info 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/ 有所錯誤歡迎指教 # [:page_with_curl: 全部文章列表](https://hackmd.io/@LHB-0222/AllWritings) ![](https://i.imgur.com/nHEcVmm.jpg)