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