WFU

[ 精選文章 ]

自行車 入門 Escape 3 , Snap 21 , Revel

最近周末想運動 , 平日想通勤 , 想買台自行車 , 把自己找的資料跟大家分享 , 如果你是玩家級的 就不用看了 這是給跟我一樣的新新新手 參考的 騎車半年後的補充: 如果你有把握你是真的有時間有興趣會一直騎,建議還是存點錢買好一點的彎把公路車, 或是可以考慮買2手的自...

2026年3月9日 星期一

Taiwan Data eXchange (TDX) 平台 的 API 整合範例 [soruce code]

使用 TDX API  得到 火車時刻表 設定起訖站 於到站前提醒

適合火車通勤工作者 下班使用

程式下載[含 原始碼]  注意需自行申請 TDX API 帳密 填入 [免費]

預覽畫面


設定畫面


TDX_Simple004.py — 程式文件


一、程式簡介

台鐵簡易時刻懸浮視窗,以半透明置頂小視窗即時顯示指定起訖站之間未來最近 N 班列車(預設 3 班),包含車種、車次、出發/抵達時間及即時誤點分鐘數。首次執行時透過對話框設定起訖站與偏好,設定值存入 tdx_simple.ini,往後啟動直接讀取,無需重複輸入。


二、概念

概念說明
懸浮視窗無邊框(overrideredirect)、常駐置頂(-topmost)、可調透明度(-alpha),不干擾其他視窗操作
OD 路線篩選OD(Origin-Destination)指定起站代碼與訖站代碼,從當日完整班表中只取中間停靠順序正確的班次
班表快取每日班表僅下載一次,以 JSON 存入 tdx_simple_cache.json,用日期字串判斷是否失效
Token 快取OAuth 2.0 Access Token 存入 tdx_token_cache.json,未過期直接複用,過期才重新取得
即時誤點另以獨立排程定期呼叫 LiveBoard API,疊加至班表顯示,與班表刷新週期分離
發車提醒計算距離發車剩餘分鐘,首次進入提醒門檻時以 Toast 視窗通知,同日同車次只提醒一次

三、執行邏輯

程式啟動
  │
  ├─ [首次] 隱藏 Tk Root → 開啟 _SetupDialog → 使用者選擇起訖站、偏好 → 寫入 .ini
  │
  └─ [已設定] 讀取 .ini → 建立 SimpleApp (主視窗)
                │
                ├─ _build_ui()   建立 Header + 車次列 × N + Status Bar
                ├─ _load_config() 讀入 OD、透明度、車種過濾、誤點刷新間隔等設定
                │
                └─ _start_fetch()  觸發資料更新
                        │
                        ├── Thread: _worker()
                        │     └─ _get_all_trains()  (快取 or API DailyTrainTimetable)
                        │     └─ _next_local_trains()  篩選 → 排序 → 取前 N 班
                        │     └─ 回主執行緒 _on_done()
                        │           └─ _render()     更新 Label 文字
                        │           └─ _check_reminder()  必要時彈出 Toast
                        │           └─ after(60s) 再次觸發 _start_fetch()
                        │
                        └── Thread: _delay_worker()
                              └─ _fetch_live_delays()  (LiveBoard API)
                              └─ 回主執行緒 _on_delays_done()
                                    └─ _render()  疊加 "+X分" 誤點顯示
                                    └─ after(delay_interval 分鐘) 再次觸發

車次篩選關鍵條件(_next_local_trains):

  1. 車種符合使用者設定(區間 / 對號)
  2. _runs_today() 解析備考欄位(「逢週X行駛/停駛」)確認今日實際行駛
  3. 起站 StopSequence < 訖站 StopSequence(方向正確)
  4. 起站發車時間 ≥ 當前時間

四、應用

  • 通勤族 — 開機常駐,不需開啟瀏覽器即可確認下一班區間車或自強號
  • 多站路線 — 支援全台主要幹線約 50 個站點,可任意設定起訖站
  • 車程追蹤 — 顯示抵達時間與即時誤點,方便規劃接駁
  • 可打包為 .exe — 配合 PyInstaller spec,可部署給無 Python 環境的使用者

五、資料來源

來源說明
TDX 平台(交通部運輸資料流通服務)https://tdx.transportdata.tw
DailyTrainTimetable API(v3)台鐵當日實際行駛班表,含所有停靠站時刻與備考
LiveBoard/Station/{id} API(v3)指定車站之列車即時進出站與誤點分鐘
OAuth 2.0 Token EndpointKeycloak Client Credentials 流程,token 有效期約 30 分鐘

六、技術分析

架構

採用單一模組 + 類別封裝結構,無框架依賴:

  • 全域函式負責 API 存取、快取讀寫、設定檔管理(純工具層)
  • _SetupDialog(tk.Toplevel) — 設定對話框,獨立生命週期
  • SimpleApp(tk.Tk) — 主視窗,持有所有狀態與排程

GUI 技術

技術用途
overrideredirect(True)去除標題列與邊框
wm_attributes("-topmost")視窗始終在最前方
wm_attributes("-alpha")半透明,可由設定調整(10%–100%)
tkfont.Font.measure()依實際字型像素寬度動態計算視窗寬度,避免各環境字型大小差異造成排版跑位
tk.Label 拖曳綁定Header 綁定 <ButtonPress-1> / <B1-Motion> 實現無邊框視窗拖曳

資料流與執行緒安全

  • 所有 I/O(API、檔案讀寫)都在 daemon=True 的背景執行緒中執行
  • 結果透過 self.after(0, callback, ...) 排回 Tk 主執行緒更新 UI,符合 tkinter 單執行緒模型要求
  • 班表刷新(60 秒)與誤點刷新(可設 1–10 分鐘)使用獨立 after 排程互不干擾

快取策略

快取檔案失效條件
OAuth Tokentdx_token_cache.jsonexpires_at - 30 秒
當日班表tdx_simple_cache.jsonCachedDate 不等於今日日期

設定持久化

使用 Python 標準函式庫 configparser(INI 格式),section [TDX_Simple] 儲存:起訖站代碼與名稱、視窗座標、透明度、顯示筆數、車種過濾、提醒分鐘數、誤點刷新間隔,共 10 個欄位,讀寫均有容錯處理。

備考解析(_runs_today

以正規表示式解析如「逢週一至五行駛」、「逢週六、日停駛」等備考字串,判斷列車今日是否實際運行,避免顯示停駛班次。

沒有留言:

張貼留言