---
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 %}