2025年7月28日 星期一

空氣品質監測小時值(一般污染物,每日更新) 之 PM2.5 ---Python TKinter

 空氣品質監測小時值(一般污染物,每日更新) 之 PM2.5 ---Python TKinter





import tkinter as tk

from tkinter import ttk

import requests

import json

from datetime import datetime


def get_pm25_specific_data():

    """

    從 API 獲取資料,篩選出 PM2.5 (細懸浮微粒),

    並提取測站代碼、測站中文名稱、監測日期和最新的 PM2.5 測值。

    """

    api_url = "https://data.moenv.gov.tw/api/v2/aqx_p_15?api_key=aa1bc2bf-24c2-4c55-980f-a12075c2caec"

    try:

        response = requests.get(api_url)

        response.raise_for_status()  # 對於錯誤的狀態碼(4xx 或 5xx)引發 HTTPError

        data = response.json()

        

        extracted_data = []

        for record in data.get('records', []):

            # 只處理 itemname 為 "細懸浮微粒" 且 itemengname 為 "PM2.5" 的資料

            if record.get('itemname') == "細懸浮微粒" and record.get('itemengname') == "PM2.5":

                site_id = record.get('siteid', 'N/A') # 新增 siteid

                site_name = record.get('sitename', 'N/A')

                monitor_date = record.get('monitordate', 'N/A')

                

                # 尋找最新的 monitorvalueXX 作為 PM2.5 測值

                latest_pm25_value = 'N/A'

                latest_hour = -1

                

                # 假設最多有 24 個小時的測值,從 00 到 23

                for i in range(24): 

                    hour_key = f'monitorvalue{i:02d}'

                    value = record.get(hour_key)

                    

                    # 檢查值是否存在、非空且不是 'nan' (某些API回傳的無效值)

                    if value is not None and value != '' and value.strip().lower() != 'nan':

                        try:

                            current_hour = int(hour_key[-2:])

                            if current_hour > latest_hour:

                                latest_hour = current_hour

                                latest_pm25_value = value

                        except ValueError:

                            pass 

                

                extracted_data.append((site_id, site_name, monitor_date, latest_pm25_value)) # 修改這裡,包含 site_id

        return extracted_data

    except requests.exceptions.RequestException as e:

        print(f"Error fetching data: {e}")

        return None


def update_pm25_display():

    """更新 PM2.5 顯示,包含測站代碼、測站中文名稱、監測日期和 PM2.5 測值。"""

    pm25_filtered_data = get_pm25_specific_data()

    

    if pm25_filtered_data:

        # 清除舊的內容

        for widget in tree.get_children():

            tree.delete(widget)


        # 插入新的資料

        for site_id, site_name, monitor_date, latest_pm25_value in pm25_filtered_data: # 修改這裡,包含 site_id

            tree.insert("", tk.END, values=(site_id, site_name, monitor_date, latest_pm25_value))

    else:

        # 如果沒有資料,顯示錯誤訊息

        for widget in tree.get_children():

            tree.delete(widget)

        tree.insert("", tk.END, values=("無法獲取 PM2.5 資料", "", "", "")) # 調整錯誤訊息欄位數

    

    # 每 5 分鐘更新一次(300000 毫秒)

    root.after(300000, update_pm25_display)


# 設定 Tkinter 視窗

root = tk.Tk()

root.title("PM2.5 即時監測 (細懸浮微粒)")


# 建立 Treeview 顯示資料

columns = ("測站代碼", "測站中文名稱", "監測日期", "PM2.5 測值") # 新增 "測站代碼"

tree = ttk.Treeview(root, columns=columns, show="headings")


for col in columns:

    tree.heading(col, text=col)

    tree.column(col, anchor=tk.CENTER, width=100) # 調整寬度


# 特別調整測站中文名稱的寬度

tree.column("測站中文名稱", width=150)

tree.column("PM2.5 測值", width=100)



tree.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)


# 執行首次更新

update_pm25_display()


# 啟動 Tkinter 事件迴圈

root.mainloop()


沒有留言:

張貼留言

ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite

 ESP32 (ESP-IDF in VS Code) MFRC522 + MQTT + PYTHON TKinter +SQLite  ESP32 VS Code 程式 ; PlatformIO Project Configuration File ; ;   Build op...