---
# System prepended metadata

title: MicroPython 空氣品質 AQI 獲取之方式
tags: [' ESP32', MicroPython, ' 江湖一點訣']

---

---
tags: MicroPython, ESP32, 江湖一點訣
image: https://i.imgur.com/tHq1qbt.jpg
description: 環保署環境資料開放平臺新版 API 需要申請 API Key，還要使用 HTTPS 連線，在通訊需加密資料量又大增的情況下，MicroPython 該如何順利取得資料?
---
# MicroPython 空氣品質 AQI 獲取之方式

> [color=#58f][name=Paoyung][time=Jul 17, 2022][:snake: ℳ𝒾𝒸𝓇ℴ𝒫𝓎𝓉𝒽ℴ𝓃 隨手記](/@PaoyungChang/mpy_trifiles)
> 
前言
---
前陣子開始聽到有在擷取環保署空氣品質 AQI 資料的夥伴們在討論，說是資料只到 2022/05/30 就沒有再更新了[^old_aqi_js]，原因是環保署環境資料開放平臺已經更新 API 版本[^epa_api2]，新版 API 必需要申請 API Key，且要求使用 SSL 才能讀取，而在通訊需加密資料量又大增的情況下，有夥伴就好奇我使用一般 WROOM 版 ESP32 的 MicroPython，是如何在「[陳大 ming.py ESP32 字量極限](/@PaoyungChang/mpy_ming_py_capacity)」中載入950個中文字的同時，還能連上環保署網站讀取資料?

[^old_aqi_js]: **舊的AQI網址**
http://opendata2.epa.gov.tw/AQI.json

[^epa_api2]: **郵件通知API更新並重新註冊** 👉[會員註冊](https://data.epa.gov.tw/api-term)<br> ![郵件通知API更新](https://i.imgur.com/tHq1qbt.jpg =240x)

江湖一點訣
---
其實並沒有什麼神奇秘訣，就只是<span class="f_b f_sz13">「使用 API 前請詳閱公開說明書」</span>。
首先先瞭解在 MicroPython 讀取 HTTP 資料最常使用的就是  urequests 模組，但它在處理資料時是把全部的內容整個傳了回來，優點是操作方便，缺點是資料內容一多記憶體就爆了[^eps32_wrover]，莫說還要做 JSON 格式轉換，除非將 urequest 改寫成能批次處理的版本，不然就必須調整讀取資料的內容量或格式。正巧新版 API 的JSON 格式就是資料量較大的這種情況(CSV格式則較小)，而通常在環保署下載的資料**並非全部都是需要的**，所以只要使用正確的參數即可取得**真正需要的部份**。我們可以在環保署[下載API參數說明手冊](https://reurl.cc/W3oAzk)，閱讀後即可發現使用 filters 這個參數就能讓資料有效的縮減。<span class="f_sz11 c_darkGreen">(減少運算量和流量也是愛地球喔！)</span>

|![參數寫法說明](https://imgur.com/efgwQRK.png)|
|--|


[^eps32_wrover]: **ESP32 Wrover**
可選用 ESP32 另外掛載 8MB PSRAM 的版本來解決記憶體不足的情況。

範例
---
有了上面的參數說明，將程式修改如下即可。<span class="c_brown f_sz11">(filters 更多的用法請參閱說明手冊)</span>
> [color=green] 採用 JSON 格式 <span class="f_sz10">(程式碼簡明易操作)</span>
```python=
import urequests
import network

def connectWifi():
    # ....
    # 請依需求自行撰寫

def getAQI(key, filters):
    url = f'https://data.epa.gov.tw/api/v2/aqx_p_432?filters={filters}&api_key={key}&format=json'
    r = urequests.get(url)
    jObj = r.json()['records']
    r.close()
    return jObj

def demo():
    # 請自行申請 api key，下面這組是無效的
    key = '8x3x0xfx-axcx-4x9x-bx3x-4x6x0xexfx8x'
    #filters = 'sitename,EQ,桃園'
    filters = 'siteid,EQ,17'
    data = getAQI(key, filters)[0]
    # 欄位都是小寫的
    print(f'縣市: {data["county"]}')
    print(f'測站名稱: {data["sitename"]}')
    print(f'AQI: {data["aqi"]}')
    print(f'PM2.5: {data["pm2.5"]}')
  
# >>> connectWifi()
# Connect OK!
# >>> demo()
#  縣市: 桃園市
#  測站名稱: 桃園
#  AQI: 33
#  PM2.5: 10
# >>>
```
> [color=green] 採用 CSV 格式 <span class="f_sz10">(需要做欄位對應)</span>

```python=
import urequests
import network

def connectWifi():
    # ....
    # 請依需求自行撰寫

def getAQI_csv(key, filters):
    url = f'https://data.epa.gov.tw/api/v2/aqx_p_432?filters={filters}&api_key={key}&format=csv'
    r = urequests.get(url)
    csv = r.text
    r.close()
    return csv

def demo_csv():
    # 請自行申請 api key，下面這組是無效的
    key = '8x3x0xfx-axcx-4x9x-bx3x-4x6x0xexfx8x'
    #filters = 'sitename,EQ,桃園'
    filters = 'siteid,EQ,17'
    lines = getAQI_csv(key, filters).split('\n')
    fields = lines[0].split(',')
    row = lines[1].split(',')
    data = {}
    for idx in range(len(fields)):
        data[fields[idx]] = row[idx]
    # 欄位都是小寫的
    print(f'縣市: {data["county"]}')
    print(f'測站名稱: {data["sitename"]}')
    print(f'AQI: {data["aqi"]}')
    print(f'PM2.5: {data["pm2.5"]}')

# >>> connectWifi()
# Connect OK!
# >>> demo_csv()
#  縣市: 桃園市
#  測站名稱: 桃園
#  AQI: 33
#  PM2.5: 10
# >>>
```


數據量比較
---
|JSON 未使用 filters|JSON 使用 filters|CSV 未使用 filters|CSV 使用 filters|
|:--:|:--:|:--:|:--:|
|約 66.6KB|約 5.1KB|約 10.1KB|👑 約 <span class="c_brown">300Bytes</span>|

聰明的你該知道怎麼選了嗎? 請多多利用此參數讓原本跑不動的程式跑起來吧！ :+1:


{%hackmd /@PaoyungChang/intro_v0702 %}


{%hackmd /@PaoyungChang/css_01 %}