2026年10月6日 星期二

NAT 是什麼?用「宿舍共用一支對外電話」來理解

網際網路入門|IP 位址與路由器

NAT 是什麼?用「宿舍共用一支對外電話」來理解

家裡、教室或辦公室裡,手機、筆電和其他設備常常一起上網。它們各有自己的內部位址,對外卻可能共用同一個公有 IP。負責協調這件事的常見功能,就是 NAT。



先想像宿舍的電話總機

一間宿舍裡住著許多學生,每個人有自己的房號或分機。學生打電話到外面時,不需要每個人都申請一支專屬的對外電話線;大家可以透過宿舍總機,共用同一個對外電話號碼。

學生的分機
各自識別
→
宿舍總機
記下通話對應
→
一個對外電話號碼
外部看到的號碼

當外面有回電時,總機會依照先前記錄的通話資訊,把電話轉到正確的分機。家用路由器執行 NAT 時,也有類似的「對外共用、內部轉送」概念。

把電話比喻換成網路

教室/家中的裝置
💻 筆電 192.168.1.10
📱 手機 192.168.1.11
🖥️ 樹莓派 192.168.1.12
各有自己的私有 IP
⇄
Wi‑Fi 路由器NAT轉換位址
記錄連線與連接埠
⇄
網際網路
☁️ 🌐
網站收到的來源位址
公有 IP:203.0.113.5
回程資料先回到路由器,再依連線紀錄送回發出請求的裝置 ↩

示意用 IP 僅供教學說明。實際網路中的公有 IP 由網路服務供應商或網路管理者配置。

一次上網請求怎麼走?

  1. 筆電以自己的私有 IP(例如 192.168.1.10)向網站提出請求。
  2. 路由器把封包的來源資訊轉換成對外使用的公有 IP,並記錄這筆連線及相關連接埠資訊。
  3. 網站回覆資料時,回覆會先到路由器的公有 IP。
  4. 路由器查詢連線紀錄,把回覆交還給原本提出請求的筆電。

同一時間,手機和樹莓派也可以建立各自的連線。路由器會用連線資訊區分它們,因此多台裝置能透過一個對外 IP 使用網路。

生活比喻與網路名詞對照

宿舍電話例子網路中的對應作用
學生的分機裝置的私有 IP識別內部網路中的裝置
宿舍對外電話號碼路由器的公有 IP讓外部網路找到這個網路出口
宿舍總機路由器的 NAT 功能轉換位址並協調內外網路的資料往返
總機的通話紀錄NAT 轉換表/連線狀態協助把回覆交給正確的內部裝置

NAT 和防火牆一樣嗎?

NAT 的主要工作是轉換網路位址;許多家用路由器也會搭配防火牆規則,限制外部連線。兩者常出現在同一台設備上,但概念不同。NAT 本身不等於完整的安全防護,仍應使用更新的路由器韌體、強密碼及適當的防火牆設定。

補充:教學中常說「多台裝置共用一個公有 IP」,通常指家用路由器常見的 IPv4 NAT/連接埠位址轉換情境。不同網路架構也可能使用 IPv6、電信商級 NAT 或其他配置。

一句話記住:多台裝置使用各自的私有 IP,透過 NAT 共用對外的公有 IP;路由器記下連線資訊,再把回覆送回正確裝置。

MQTT 與 IoT 雙向通訊|Pico 2 W

Pico 2 W × Thonny|第 6 次課程

MQTT 與 IoT 雙向通訊

前一篇已把感測資料整理成 JSON。本篇將資料放進 MQTT 訊息,讓 Pico 2 W 發布感測資料,也訂閱控制主題接收命令。這樣裝置不只會「上傳」,也能從網路接收控制,形成 IoT 的雙向通訊。

一、MQTT 的三個角色

MQTT 使用 Broker(訊息代理伺服器)中轉訊息。Publisher 將訊息發布到某個 Topic;Subscriber 訂閱感興趣的 Topic。Broker 依照訂閱關係轉送訊息,因此 Publisher 通常不需要知道每一個 Subscriber 的網路位置。

Publisher 發布者把訊息送到指定 Topic,例如 Pico 上傳感測資料。
Broker 代理伺服器接收、管理並轉送訊息,是通訊中介。
Subscriber 訂閱者訂閱 Topic 並接收訊息,例如電腦 Dashboard。

同一台 Pico 可以同時扮演 Publisher 與 Subscriber:它發布感測值,也訂閱控制命令。

二、Topic 是訊息的分類路徑

Topic 用來標示訊息的類別或用途。好的命名方式能看出位置、設備與功能,讓多個裝置加入時仍然容易管理。

farm/room01/pico01/telemetry
farm/room01/pico01/status
farm/room01/pico01/control

farm/room02/pico02/telemetry
  • telemetry:感測器或設備定期發布的遙測資料。
  • status:設備目前狀態。
  • control:送往設備的控制命令。

Topic 名稱要在發布端和訂閱端完全一致;斜線分隔的層級也要保持規則一致。

三、Publish:Pico 發布感測資料

發布時要指定 Topic 和 Payload(訊息內容)。Topic 說明這是哪一類訊息,Payload 則放實際資料。本課程沿用上一堂的 JSON 格式,因此接收端可以依照欄位名稱解析資料。

import json

topic_telemetry = b"farm/room01/pico01/telemetry"

# 這些數字只用來示範資料格式
payload = {
    "temperature": 28.3,
    "humidity": 71.2
}

client.publish(
    topic_telemetry,
    json.dumps(payload)
)

範例中的數字只是格式示意,不是實際場域資料。實作時應換成感測器讀值,並確認欄位名稱、型態與單位已事先約定。

四、Subscribe:Pico 訂閱控制命令

Dashboard 或電腦可以把控制命令發布到設備的 control Topic。Pico 訂閱這個 Topic,收到訊息後解析 JSON,再依內容控制 GPIO。

import json
from machine import Pin

led = Pin("LED", Pin.OUT)

def on_message(topic, message):
    print("Topic:", topic)
    print("Message:", message)

    try:
        command = json.loads(message.decode())

        if "relay" in command:
            led.value(1 if command["relay"] else 0)
            print("LED updated:", led.value())

    except (ValueError, KeyError) as error:
        print("Invalid command:", error)

topic_control = b"farm/room01/pico01/control"
client.set_callback(on_message)
client.subscribe(topic_control)

命令可以是 {"relay": true}或 {"relay": false}。實際系統應依設備功能設計命令欄位,並確認收到的內容合法後才執行控制。

五、Pico 連接 Broker 並雙向交換訊息

以下是教學架構範例,假設 Pico 已先連上 Wi-Fi,且韌體已提供相容的 umqtt.simple用戶端。請把 Broker 主機、帳號與密碼替換成教師提供的測試設定。Broker 的網路位置與連線方式依服務而異。

import json
import time
from umqtt.simple import MQTTClient

BROKER = "請填入 MQTT Broker 主機"
CLIENT_ID = b"pico-room01-device01"

TOPIC_TELEMETRY = b"farm/room01/pico01/telemetry"
TOPIC_CONTROL = b"farm/room01/pico01/control"

# 若測試 Broker 不需要帳密,可依用戶端規格省略相關參數
client = MQTTClient(CLIENT_ID, BROKER)

def on_message(topic, message):
    print("Received:", topic, message)
    # 在此解析控制命令並更新 GPIO

client.set_callback(on_message)
client.connect()
client.subscribe(TOPIC_CONTROL)

print("MQTT connected and subscribed")

while True:
    # 示範內容;實作時改成感測器的實際讀值
    telemetry = {
        "temperature": 28.3,
        "humidity": 71.2
    }

    client.publish(
        TOPIC_TELEMETRY,
        json.dumps(telemetry)
    )

    # 檢查是否有訂閱訊息;有訊息時會呼叫 on_message
    client.check_msg()

    time.sleep(5)

set_callback()設定收到訊息時要執行的函式;subscribe()訂閱控制 Topic;publish()發布感測資料;check_msg()檢查是否有新訊息。這個程式每五秒發布一次示範資料,實際量測值需由感測器取得。

套件與 Broker:不同 MicroPython 韌體不一定預先包含 umqtt.simple,需先確認課堂環境的套件安裝方式。此範例使用提示文字作為 Broker 主機,並非可直接連線的服務。

六、MQTT 與 HTTP 如何搭配?

HTTP常見為 Request/Response,適合網頁與 API 的一次性資料交換。
MQTT使用 Publish/Subscribe,適合設備持續發布遙測資料或接收命令。
共同點兩者都在 IP 網路上運作,都必須考慮斷線與錯誤處理。

HTTP 和 MQTT 各有適合的情境,IoT 系統也可以同時使用兩者。例如設備透過 MQTT 傳送即時遙測,而設定頁面或其他服務使用 HTTP API。

七、斷線與安全性

Wi-Fi 或 Broker 可能中斷,設備程式要能顯示連線狀態,並設計清楚的重新連線流程。重新連線後,通常也要重新訂閱控制 Topic。不要在故障時無限快速重試;可採用有限次數與間隔,並讓錯誤訊息容易辨識。

保護 Broker 憑證:不要把真實帳密、Token 或 API Key 放進公開投影片、部落格或 Git 儲存庫。控制 Topic 會影響實體輸出,應使用可信任的 Broker、限制可發布者,並在接收端檢查命令內容。

八、實作任務:完成第一個 MQTT IoT Node

  1. 連上課堂指定 Wi-Fi。
  2. 連接測試 MQTT Broker。
  3. 訂閱設備的 control Topic。
  4. 每五秒發布一筆感測器 JSON 到 telemetry Topic。
  5. 從 Dashboard 或測試用戶端發布控制命令,確認 Pico 收到後能更新 GPIO。
  6. 挑戰:Wi-Fi 或 Broker 斷線後,顯示狀態並完成重新連線與重新訂閱。

測試時,建議同時觀察 Pico 的 Thonny Shell 與 Broker 用戶端畫面,確認每一筆訊息的 Topic、Payload 和方向。

六次課程如何串成完整資料流

  1. 第 1 次:控制硬體,建立 GPIO 基礎。
  2. 第 2 次:連上 Wi-Fi,取得網路資訊。
  3. 第 3 次:建立 Web Server,讓瀏覽器控制 Pico。
  4. 第 4 次:透過 HTTP 與 API 交換資料。
  5. 第 5 次:以 JSON 建立一致的資料格式。
  6. 第 6 次:以 MQTT 發布遙測資料並接收控制命令。

完成這六次課程後,就具備 IoT 專題的基本通訊流程。下一階段可以接續設計 Dashboard 或 IoT 平台,讓資料能被觀察、整理與應用。

Pico 2 W × Thonny|第 6 次課程

MQTT 與 IoT 雙向通訊

前一篇已把感測資料整理成 JSON。本篇將資料放進 MQTT 訊息,讓 Pico 2 W 發布感測資料,也訂閱控制主題接收命令。這樣裝置不只會「上傳」,也能從網路接收控制,形成 IoT 的雙向通訊。

一、MQTT 的三個角色

MQTT 使用 Broker(訊息代理伺服器)中轉訊息。Publisher 將訊息發布到某個 Topic;Subscriber 訂閱感興趣的 Topic。Broker 依照訂閱關係轉送訊息,因此 Publisher 通常不需要知道每一個 Subscriber 的網路位置。

Publisher 發布者把訊息送到指定 Topic,例如 Pico 上傳感測資料。
Broker 代理伺服器接收、管理並轉送訊息,是通訊中介。
Subscriber 訂閱者訂閱 Topic 並接收訊息,例如電腦 Dashboard。

同一台 Pico 可以同時扮演 Publisher 與 Subscriber:它發布感測值,也訂閱控制命令。

二、Topic 是訊息的分類路徑

Topic 用來標示訊息的類別或用途。好的命名方式能看出位置、設備與功能,讓多個裝置加入時仍然容易管理。

farm/room01/pico01/telemetry
farm/room01/pico01/status
farm/room01/pico01/control

farm/room02/pico02/telemetry
  • telemetry:感測器或設備定期發布的遙測資料。
  • status:設備目前狀態。
  • control:送往設備的控制命令。

Topic 名稱要在發布端和訂閱端完全一致;斜線分隔的層級也要保持規則一致。

三、Publish:Pico 發布感測資料

發布時要指定 Topic 和 Payload(訊息內容)。Topic 說明這是哪一類訊息,Payload 則放實際資料。本課程沿用上一堂的 JSON 格式,因此接收端可以依照欄位名稱解析資料。

import json

topic_telemetry = b"farm/room01/pico01/telemetry"

# 這些數字只用來示範資料格式
payload = {
    "temperature": 28.3,
    "humidity": 71.2
}

client.publish(
    topic_telemetry,
    json.dumps(payload)
)

範例中的數字只是格式示意,不是實際場域資料。實作時應換成感測器讀值,並確認欄位名稱、型態與單位已事先約定。

四、Subscribe:Pico 訂閱控制命令

Dashboard 或電腦可以把控制命令發布到設備的 control Topic。Pico 訂閱這個 Topic,收到訊息後解析 JSON,再依內容控制 GPIO。

import json
from machine import Pin

led = Pin("LED", Pin.OUT)

def on_message(topic, message):
    print("Topic:", topic)
    print("Message:", message)

    try:
        command = json.loads(message.decode())

        if "relay" in command:
            led.value(1 if command["relay"] else 0)
            print("LED updated:", led.value())

    except (ValueError, KeyError) as error:
        print("Invalid command:", error)

topic_control = b"farm/room01/pico01/control"
client.set_callback(on_message)
client.subscribe(topic_control)

命令可以是 {"relay": true}或 {"relay": false}。實際系統應依設備功能設計命令欄位,並確認收到的內容合法後才執行控制。

五、Pico 連接 Broker 並雙向交換訊息

以下是教學架構範例,假設 Pico 已先連上 Wi-Fi,且韌體已提供相容的 umqtt.simple用戶端。請把 Broker 主機、帳號與密碼替換成教師提供的測試設定。Broker 的網路位置與連線方式依服務而異。

import json
import time
from umqtt.simple import MQTTClient

BROKER = "請填入 MQTT Broker 主機"
CLIENT_ID = b"pico-room01-device01"

TOPIC_TELEMETRY = b"farm/room01/pico01/telemetry"
TOPIC_CONTROL = b"farm/room01/pico01/control"

# 若測試 Broker 不需要帳密,可依用戶端規格省略相關參數
client = MQTTClient(CLIENT_ID, BROKER)

def on_message(topic, message):
    print("Received:", topic, message)
    # 在此解析控制命令並更新 GPIO

client.set_callback(on_message)
client.connect()
client.subscribe(TOPIC_CONTROL)

print("MQTT connected and subscribed")

while True:
    # 示範內容;實作時改成感測器的實際讀值
    telemetry = {
        "temperature": 28.3,
        "humidity": 71.2
    }

    client.publish(
        TOPIC_TELEMETRY,
        json.dumps(telemetry)
    )

    # 檢查是否有訂閱訊息;有訊息時會呼叫 on_message
    client.check_msg()

    time.sleep(5)

set_callback()設定收到訊息時要執行的函式;subscribe()訂閱控制 Topic;publish()發布感測資料;check_msg()檢查是否有新訊息。這個程式每五秒發布一次示範資料,實際量測值需由感測器取得。

套件與 Broker:不同 MicroPython 韌體不一定預先包含 umqtt.simple,需先確認課堂環境的套件安裝方式。此範例使用提示文字作為 Broker 主機,並非可直接連線的服務。

六、MQTT 與 HTTP 如何搭配?

HTTP常見為 Request/Response,適合網頁與 API 的一次性資料交換。
MQTT使用 Publish/Subscribe,適合設備持續發布遙測資料或接收命令。
共同點兩者都在 IP 網路上運作,都必須考慮斷線與錯誤處理。

HTTP 和 MQTT 各有適合的情境,IoT 系統也可以同時使用兩者。例如設備透過 MQTT 傳送即時遙測,而設定頁面或其他服務使用 HTTP API。

七、斷線與安全性

Wi-Fi 或 Broker 可能中斷,設備程式要能顯示連線狀態,並設計清楚的重新連線流程。重新連線後,通常也要重新訂閱控制 Topic。不要在故障時無限快速重試;可採用有限次數與間隔,並讓錯誤訊息容易辨識。

保護 Broker 憑證:不要把真實帳密、Token 或 API Key 放進公開投影片、部落格或 Git 儲存庫。控制 Topic 會影響實體輸出,應使用可信任的 Broker、限制可發布者,並在接收端檢查命令內容。

八、實作任務:完成第一個 MQTT IoT Node

  1. 連上課堂指定 Wi-Fi。
  2. 連接測試 MQTT Broker。
  3. 訂閱設備的 control Topic。
  4. 每五秒發布一筆感測器 JSON 到 telemetry Topic。
  5. 從 Dashboard 或測試用戶端發布控制命令,確認 Pico 收到後能更新 GPIO。
  6. 挑戰:Wi-Fi 或 Broker 斷線後,顯示狀態並完成重新連線與重新訂閱。

測試時,建議同時觀察 Pico 的 Thonny Shell 與 Broker 用戶端畫面,確認每一筆訊息的 Topic、Payload 和方向。

六次課程如何串成完整資料流

  1. 第 1 次:控制硬體,建立 GPIO 基礎。
  2. 第 2 次:連上 Wi-Fi,取得網路資訊。
  3. 第 3 次:建立 Web Server,讓瀏覽器控制 Pico。
  4. 第 4 次:透過 HTTP 與 API 交換資料。
  5. 第 5 次:以 JSON 建立一致的資料格式。
  6. 第 6 次:以 MQTT 發布遙測資料並接收控制命令。

完成這六次課程後,就具備 IoT 專題的基本通訊流程。下一階段可以接續設計 Dashboard 或 IoT 平台,讓資料能被觀察、整理與應用。

JSON 與 IoT 資料格式|Pico 2 W

Pico 2 W × Thonny|第 5 次課程

JSON 與 IoT 資料格式

感測器產生資料,Pico 負責整理與傳送;要讓不同設備、程式和伺服器都能理解同一筆資訊,就需要清楚一致的資料格式。本篇介紹 JSON 的基本結構、Python 字典與 JSON 的轉換,以及 IoT 遙測欄位的設計方法。

作者:施朝斌

一、為什麼 IoT 需要 JSON?

如果只傳送 28.3,71.2,350,接收端雖然看到三個數字,卻不知道它們各自代表溫度、濕度還是光照。JSON 在資料旁附上欄位名稱,讓資料較容易閱讀,也讓程式能依欄位取值。

{
  "temperature": 28.3,
  "humidity": 71.2,
  "light": 350
}

以上數字沿用課程投影片作為格式示例,不代表實際場域量測結果。正式資料應由感測器讀取,並清楚標明單位與資料來源。

二、JSON 的基本結構

JSON 物件使用大括號 {},以「欄位名稱:值」的方式組織資料;陣列使用中括號 [],可以放置多筆項目。常見值的型態包括字串、數字、布林值、物件、陣列,以及 null。

{
  "device": "PICO01",
  "temperature": 28.3,
  "humidity": 71.2,
  "relay": true,
  "location": {
    "room": "A101"
  },
  "alerts": []
}
  • 字串:文字需使用雙引號,例如 "PICO01"。
  • 數字:例如 28.3;不要把數字不必要地存成文字。
  • 布林值:使用小寫的 true 或 false。
  • 物件:可再包含一組欄位,例如 location。
  • 陣列:使用中括號,可表示多筆資料或多個項目。
  • null:表示目前沒有可用值;它不同於字串 "null"或數字 0。

三、Python 字典與 JSON 互相轉換

在 Python 程式中,資料常先以字典整理。json.dumps()把 Python 資料轉成 JSON 文字;json.loads()則把 JSON 文字解析回 Python 資料。

import json

data = {
    "temperature": 28.3,
    "humidity": 71.2,
    "relay": True
}

json_text = json.dumps(data)
print(json_text)

decoded_data = json.loads(json_text)
print(decoded_data["temperature"])

Python 的 True轉成 JSON 後會是小寫的 true;JSON 解析回 Python 後則會成為 True。同樣地,Python 的 None會轉成 JSON 的 null。

兩個常見動詞:dumps把資料「序列化」成文字;loads把文字「解析」成資料。HTTP 傳輸時,送出或收到的通常是文字內容。

四、設計 IoT 遙測資料欄位

一筆可交換的遙測資料,除了感測值,也應讓接收端知道資料來自哪個設備、何時產生,以及每個數字代表什麼。欄位名稱與格式最好固定,後續接入 HTTP API、MQTT 或 Dashboard 時才能共用。

{
  "deviceId": "PICO01",
  "timestamp": null,
  "temperature": 28.3,
  "humidity": 71.2,
  "light": 350,
  "battery": 4.05
}

這些感測值是投影片中的示範數字,不是實際量測結果。timestamp目前設為 null,表示範例沒有提供時間;只有在 Pico 已取得可靠時鐘並採用一致的時間格式後,才應填入時間戳記。每個欄位也應訂定單位,例如溫度使用 °C、電壓使用 V,避免不同設備各自解讀。

設計欄位時,還要決定設備識別方式、欄位拼法、數值型態、單位、取樣時間與缺值表示法。這些規則就是資料格式的一部分。

五、用 Python 建立自己的 JSON 遙測資料

以下以示範值展示資料結構。實作時請把數值換成程式實際讀到的感測器資料;若某欄位目前沒有讀值,使用 None轉成 JSON null,不要假裝已取得測量結果。

import json

telemetry = {
    "deviceId": "PICO01",
    "timestamp": None,
    "temperature": 28.3,
    "humidity": 71.2,
    "relay": False
}

payload = json.dumps(telemetry)
print(payload)

接著可以把 payload放進 HTTP POST 的 Body,或在下一堂課將它作為 MQTT 訊息內容。只要欄位規則維持一致,接收端就能用相同方式解析。

六、錯誤資料也要處理

網路上的資料不一定完整、型態正確或仍然新鮮。接收端應先檢查必需欄位,再確認型態與時間資訊,並適當處理伺服器錯誤。

import json

response_text = '{"temperature": 28.3}'

try:
    data = json.loads(response_text)

    temperature = data.get("temperature")
    humidity = data.get("humidity")

    if temperature is None:
        print("Temperature is missing")
    elif not isinstance(temperature, (int, float)):
        print("Temperature has the wrong type")
    else:
        print("Temperature:", temperature)

    if humidity is None:
        print("Humidity is missing")
    else:
        print("Humidity:", humidity)

except ValueError as error:
    print("Invalid JSON:", error)
  • 欄位不存在:使用 get()或明確檢查,避免直接索引而產生 KeyError。
  • 型態錯誤:數字 28.3與文字 "28.3"不是同一種資料。
  • 資料過期:若有可靠時間戳記,可比較資料時間與目前時間;沒有時鐘時不要假裝能判定新舊。
  • 伺服器錯誤:檢查 HTTP 狀態碼,必要時有限次重試並記錄結果。

七、REST API 路徑與資料責任

REST API 常用不同路徑區分資源或功能。例如 /api/telemetry可代表感測資料、/api/status可代表設備狀態、/api/control可代表控制要求、/api/config可代表設定資訊。路徑名稱只是設計示例,實際 API 應依服務規格使用。

把感測資料、設備狀態、控制命令與設定分開,有助於開發者理解每個端點的用途。欄位名稱與格式也要在設備端和伺服器端保持一致。

八、實作任務:定義自己的 Pico 資料格式

  1. 建立一個穩定的 deviceId。
  2. 選擇 2 至 3 個實際存在或課堂指定的感測欄位。
  3. 加入一個設備狀態欄位,例如繼電器開關狀態。
  4. 為每個欄位記錄型態、單位與缺值表示方式。
  5. 使用 json.dumps()轉成 JSON,並在 Shell 檢查輸出。
  6. 依課程提供的測試服務 POST,檢查狀態碼與回應內容。
不要把示範數據當成實測結果:完成實驗紀錄時,註明數值來自範例、模擬器或實際感測器。若來源不同,也要避免混在一起比較或宣稱為場域成效。

本篇重點回顧

  • JSON 以欄位名稱標示資料意義,方便不同設備和程式交換資訊。
  • Python 字典可用 json.dumps()轉為 JSON 文字,用 json.loads()解析回資料。
  • IoT 遙測格式應固定欄位名稱、型態、單位、設備識別與時間規則。
  • 要檢查欄位缺漏、型態不符、資料是否過期及 HTTP 錯誤。
  • 範例數值只示範格式;實際結果應來自感測器或明確標示的測試資料。

下一篇將把一致的 JSON 遙測資料帶入 MQTT,讓 Pico 發布感測訊息,也能訂閱控制命令。

HTTP 與 REST API|Pico 2 W

Pico 2 W × Thonny|第 4 次課程

HTTP 與 REST API

前三次課程讓 Pico 2 W 控制硬體、連上 Wi-Fi,並提供自己的網頁服務。本篇把角色反過來:Pico 成為 HTTP Client,主動向 Internet 上的 API 取得資料,或把感測資料送到遠端服務。

作者:施朝斌

一、從 Web Server 走向 API Client

使用 Pico Web Server 時,手機或電腦的瀏覽器主動連進 Pico;使用遠端 API 時,則是 Pico 主動連到 API Server。API(應用程式介面)提供一組約定好的網址與資料格式,讓程式可以透過網路交換資訊。

HTTP ClientPico 發出要求,等待遠端服務回應。
API Server接收要求、處理資料,再回覆結果。
URL指出要存取的服務或資源位置。
JSON常見的資料格式,能以欄位名稱與值描述資料。

二、GET 與 POST:讀取資料和送出資料

GET 通常用來讀取某個資源,例如查詢天氣或取得感測器資料。POST 通常用來送出資料,例如把 Pico 讀到的感測值傳到伺服器。實際 API 會規定可用的方法、網址、欄位與驗證方式,因此呼叫前要先閱讀服務文件。

  • GET:向 API 詢問資料,常見形式是 GET /api/data。
  • POST:將資料送給 API,常見形式是 POST /api/telemetry。
  • Header:提供內容類型、授權資訊等要求或回應的附加資料。
  • Body:HTTP 要求或回應承載的內容;POST 常把 JSON 放在 Body。

GET 和 POST 是常見用途,不代表每個服務都完全相同。API 文件才是判斷端點、欄位、授權與資料格式的依據。

三、HTTP 狀態碼:先看請求結果

伺服器回應時會提供狀態碼,告訴 Client 這次要求大致如何處理。程式不能只假設回應一定成功,應先檢查狀態碼,再決定要解析回應資料或顯示錯誤。

200 OK要求成功,通常可讀取回傳內容。
201 Created伺服器成功建立了資源。
400 Bad Request要求格式或內容不符合服務規則。
404 Not Found指定的資源或路徑不存在。
500 Server Error伺服器處理時發生錯誤。

狀態碼是診斷線索:例如 404 可先檢查 URL 路徑,400 可檢查送出的欄位與 JSON 格式,5xx 則可能需要稍後重試或聯絡服務提供者。

四、Pico 使用 HTTP POST 傳送資料

投影片以 urequests 示範 HTTP Client。以下資料只是格式示範,不是實際養殖或場域量測值。請將 URL 換成教師提供且允許測試的 API 端點,並依服務文件調整欄位。

import urequests

url = "https://api.example.org/telemetry"

data = {
    "device_id": "pico-demo-01",
    "temperature": 28.3,
    "humidity": 71.2
}

response = None

try:
    response = urequests.post(url, json=data)
    print("Status:", response.status_code)
    print("Response:", response.text)
except Exception as error:
    print("Request failed:", error)
finally:
    if response is not None:
        response.close()

urequests.post(url, json=data)會把 Python 字典轉成 JSON 格式送出。伺服器回應後,程式讀取 status_code與回應文字;不論成功或失敗,都在 finally區塊關閉 Response,釋放網路資源。

端點提醒:api.example.org是示意網址,不能當成真實課程 API 使用。需替換成已確認可用、且允許 POST 測試的服務。不同 MicroPython 韌體可能需要另外安裝或提供 urequests模組。

五、Pico 使用 HTTP GET 讀取資料

GET 的流程相似,只是呼叫方式改為 urequests.get()。若 API 回傳 JSON,可以使用 response.json()將內容轉為 Python 資料結構,再取出需要的欄位。

import urequests

url = "https://api.example.org/data"
response = None

try:
    response = urequests.get(url)
    print("Status:", response.status_code)

    if response.status_code == 200:
        result = response.json()
        print("Returned data:", result)
    else:
        print("Server returned an error")
except Exception as error:
    print("Request failed:", error)
finally:
    if response is not None:
        response.close()

若回應不是合法 JSON,或伺服器回傳錯誤頁面,response.json()可能無法解析。因此先檢查狀態碼,再讀取資料,是比較可靠的順序。

六、一次完整的資料交換流程

  1. 確認 Pico 已連上 Wi-Fi,並能使用目標網路服務。
  2. 閱讀 API 文件,確認 URL、HTTP 方法、必要欄位與授權方式。
  3. 整理感測資料;送出前確認欄位名稱、資料型態與單位。
  4. 發出 GET 或 POST 要求,等待伺服器回應。
  5. 先檢查狀態碼,再解析回應內容。
  6. 關閉 Response,並記錄成功或錯誤訊息。

以 IoT 遙測為例,資料由感測器進入 Pico,程式整理成 JSON,再透過 HTTP POST 傳到 API Server。重點是理解資料如何跨網路移動,而不是記住某一家 API 的名稱。

七、網路程式的三個陷阱

  • Timeout:伺服器可能很慢或暫時沒有回應,程式不應無限等待。
  • Disconnect:Wi-Fi 可能中斷;需要辨認連線失敗,並依課程設計決定是否重新連線。
  • Memory:回應內容可能很大;微控制器記憶體有限,避免不加判斷地讀取大型資料。

建立「逾時、例外處理、有限次重試、關閉 Response」的習慣,能讓網路程式更容易除錯。重試也要有限次數,並避免在服務故障時快速重複送出大量請求。

八、實作任務

  • GET 一個課堂指定、可公開讀取的測試 API。
  • 列印狀態碼,並從 JSON 回應中取出一個指定欄位。
  • 使用測試資料 POST 到教師指定的測試端點。
  • 在 Shell 顯示狀態碼與伺服器回應。
  • 挑戰:遇到連線失敗時,有限次重試並印出清楚的錯誤原因。
API 金鑰與個人資料:若服務要求 Token 或 API Key,不要將它貼在公開投影片、部落格或 Git 儲存庫中。練習應使用教師核准的測試憑證與測試資料。

本篇重點回顧

  • Pico 可以當 HTTP Client,主動向遠端 API 讀取或傳送資料。
  • GET 常用於取得資料,POST 常用於送出資料;實際格式依 API 文件為準。
  • 狀態碼提供伺服器處理結果,應先檢查再解析回應。
  • 使用 JSON 傳遞感測資料時,要留意欄位、型態與單位。
  • 網路程式要處理逾時、斷線、錯誤與記憶體限制,並關閉 Response。

下一篇將把感測資料整理成一致的 JSON 格式,進一步理解資料欄位、時間戳記與錯誤資料處理。

Pico Web Server 與網頁控制

Pico 2 W × Thonny|第 3 次課程

Pico Web Server 與網頁控制

前一堂讓 Pico 2 W 加入 Wi-Fi 網路;這一堂進一步讓它成為 Web Server。手機或電腦用瀏覽器連到 Pico 的 IP,讀取它送出的網頁,再透過網址路徑送出控制要求,讓板載 LED 亮起或熄滅。

作者:施朝斌

一、瀏覽器與 Pico 如何對話?

當瀏覽器開啟一個網址,它會扮演 Client(用戶端),向提供服務的設備送出 HTTP Request(請求)。Pico 扮演 Server(伺服端),接收請求後回傳 HTTP Response(回應),內容可以是 HTML 網頁,也可以是文字或 JSON。

Client手機或電腦上的瀏覽器,提出網頁或控制要求。
Request瀏覽器送出的要求,例如讀取首頁或請求 /on。
Server等待連線、讀取要求並決定如何處理的 Pico 程式。
ResponsePico 回傳的狀態、標頭與網頁內容。

HTTP 通訊通常使用 TCP 連線。簡化來看,伺服器建立 Socket、綁定連接埠並等待連線;瀏覽器連進來後,伺服器讀取 Request、組成 Response、傳送回去,再關閉這次連線。

二、URL 路徑可以代表控制命令

本課程把不同路徑當作簡單命令:瀏覽器要求 /on,Pico 就開啟 LED;要求 /off,Pico 就關閉 LED;要求 /status,則回傳目前 LED 狀態。瀏覽器並不是直接碰觸 GPIO,而是把 HTTP 要求交給 Pico,由 Pico 程式執行控制。

資料流:瀏覽器點選控制連結 → 傳送 HTTP Request → Pico 解析路徑 → 程式控制 LED → Pico 回傳網頁。

三、建立第一個 Pico Web Server

以下範例把前一堂的 Wi-Fi 連線與本堂的 HTTP Server 串在一起。請先將 SSID 和 PASSWORD 換成課堂核准的測試網路資訊,執行程式後從 Shell 記下 Pico 顯示的 IP,再用同一個區域網路內的手機或電腦瀏覽器開啟該位址。

import network
import socket
import time
from machine import Pin

SSID = "請填入 Wi-Fi 名稱"
PASSWORD = "請填入 Wi-Fi 密碼"
HTTP_PORT = 80

led = Pin("LED", Pin.OUT)
led.value(0)

# 連接 Wi-Fi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)

for attempt in range(20):
    if wlan.isconnected():
        break
    print("Connecting...", attempt + 1)
    time.sleep(1)

if not wlan.isconnected():
    raise RuntimeError("Wi-Fi connection failed")

ip_address = wlan.ifconfig()[0]
print("Open this address in a browser:", ip_address)

# 建立並啟動 Web Server
address = socket.getaddrinfo("0.0.0.0", HTTP_PORT)[0][-1]
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(address)
server.listen(1)

print("Web Server is ready")

while True:
    client, client_address = server.accept()
    try:
        request = client.recv(1024)
        request_text = request.decode()
        print("Request:", request_text.split("\r\n")[0])

        request_line = request_text.split("\r\n")[0]
        parts = request_line.split(" ")
        path = parts[1] if len(parts) > 1 else "/"

        if path == "/on":
            led.value(1)
        elif path == "/off":
            led.value(0)

        if path not in ("/", "/on", "/off", "/status"):
            status_line = "HTTP/1.0 404 Not Found"
            message = "Page not found"
        else:
            status_line = "HTTP/1.0 200 OK"
            message = "LED is ON" if led.value() else "LED is OFF"

        page = """<!doctype html>
<html lang="en">
<head><meta charset="utf-8"><title>Pico Control</title></head>
<body>
  <h1>Pico 2 W Control Panel</h1>
  <p>Current status: {}</p>
  <p><a href="/on">LED ON</a> | <a href="/off">LED OFF</a> | <a href="/status">Refresh status</a></p>
</body>
</html>""".format(message)

        response = (
            status_line + "\r\n"
            + "Content-Type: text/html; charset=utf-8\r\n"
            + "Connection: close\r\n"
            + "\r\n"
            + page
        )
        client.send(response.encode())

    except Exception as error:
        print("Request handling error:", error)
    finally:
        client.close()

Socket 綁定在 0.0.0.0,表示接受本機各網路介面的連線;HTTP 使用的連接埠是 80。程式在 Shell 印出 IP 後會持續等待瀏覽器連線,所以 Thonny 要保持程式執行中。若按 Stop,Web Server 也會停止。

四、HTML 只是 Pico 傳出的文字

Pico 不會像電腦一樣替你「畫出」網頁;它把 HTML 文字放進 HTTP Response,瀏覽器再負責解析與顯示。範例中的標題、狀態文字和連結都由 HTML 組成。修改標題或按鈕名稱,就能改變瀏覽器看到的控制面板。

這裡使用連結 <a href="/on">與 <a href="/off">,點選後瀏覽器會重新向 Pico 發出新要求。伺服器根據網址路徑執行對應動作,並回傳更新後的狀態。

五、第一次測試與除錯

  1. 確認 Pico 已連上 Wi-Fi,Shell 顯示取得的 IP 位址。
  2. 確認程式已印出 Web Server ready,且仍在執行。
  3. 手機或電腦連到與 Pico 相同、且允許裝置互通的區域網路。
  4. 在瀏覽器輸入 http:// 加上 Pico 的 IP 位址,例如 http://192.168.x.x;實際 IP 以你的程式輸出為準。
  5. 點選 LED ON、LED OFF,觀察板載 LED,並查看 Shell 是否印出 Request。

如果網頁打不開,依序確認:Pico 是否有 IP、Server 是否仍在執行、瀏覽器是否使用正確 IP、裝置是否能互相連線,以及 Request 是否到達 Pico。校園或公共 Wi-Fi 可能啟用用戶端隔離,讓同一 Wi-Fi 的裝置也無法彼此連線;這時可改用經教師同意的測試網路。

六、實作挑戰:做自己的控制面板

  • 將首頁標題改成自己的裝置名稱。
  • 在頁面顯示 Pico 的 IP 與 Wi-Fi 連線狀態。
  • 新增 /status 路徑,顯示 LED 開或關。
  • 加入一個 ADC 或感測器讀值,讓網頁同時呈現狀態與資料。
  • 設計不同顏色的按鈕,或加入定時重新整理狀態的功能。
網路安全:這個入門伺服器沒有登入驗證,也沒有加密,只適合在可信任的教學區域網路中練習。不要將它直接暴露到公共 Internet,也不要在公開程式中留下真實 Wi-Fi 密碼。

本篇重點回顧

  • 瀏覽器是 Client,Pico Web Server 是 Server;兩者透過 HTTP Request 與 Response 溝通。
  • Socket 程式負責等待連線、讀取請求、傳送回應與關閉連線。
  • 網址路徑可對應控制命令,例如 /on與 /off。
  • Pico 傳送 HTML 文字,瀏覽器負責呈現畫面。
  • 除錯時先確認 IP、伺服器狀態、網路互通與 Request 是否到達。

下一篇將從「瀏覽器連進 Pico」走向「Pico 主動向外送資料」,認識 HTTP GET/POST 與 REST API。

Wi-Fi、IP 與網際網路連線|Pico 2 W

Pico 2 W × Thonny|第 2 次課程

Wi-Fi、IP 與網際網路連線

Pico 2 W 連上 Wi-Fi,只代表它加入了無線區域網路。要和其他網路或 Internet 上的服務通訊,還需要網路位址、閘道器與 DNS 等資訊。本篇帶你逐步連線、查看設定,並用明確的順序排查問題。

作者:施朝斌

一、Wi-Fi 不等於 Internet

Wi-Fi 是裝置連接無線基地台(AP)的方式;Internet 則是由許多網路互相連接而成。Pico 成功連上基地台,是通訊的第一步,但基地台或校園網路仍可能受到登入驗證、網路政策或外部連線限制,因此「已連上 Wi-Fi」不一定表示「已能使用 Internet」。

Wi-Fi/AP讓 Pico 以無線方式加入區域網路。
IP 位址標示 Pico 在網路中的位置,讓資料知道要送給哪一部裝置。
Gateway通常是路由器,負責把資料從本地網路轉送到其他網路。
DNS協助把網域名稱查詢成 IP 位址。

可以用「校園地址」來想像:IP 像裝置的門牌,Gateway 像通往外部道路的出口,DNS 則像依照名稱查找地址的服務。

二、讓 Pico 2 W 連上 Wi-Fi

MicroPython 使用 network 模組管理無線網路。以下範例將 Pico 設為站台模式(Station),啟用 Wi-Fi,並使用課堂提供的網路名稱與密碼嘗試連線。

import network
import time

SSID = "請填入 Wi-Fi 名稱"
PASSWORD = "請填入 Wi-Fi 密碼"

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(SSID, PASSWORD)

for attempt in range(20):
    if wlan.isconnected():
        break
    print("Connecting...", attempt + 1)
    time.sleep(1)

if wlan.isconnected():
    print("Connected!")
    print("Network settings:", wlan.ifconfig())
else:
    print("Connection failed. Check SSID, password, and network access.")

network.STA_IF表示 Pico 要連到既有的無線基地台,而不是自行建立基地台。active(True)啟用無線介面;connect()開始連線;isconnected()檢查連線狀態。範例設定最多等待約 20 秒,避免程式一直停在等待迴圈中。

保護網路密碼:請使用教師核准的測試網路或自己的行動熱點。不要把真實 Wi-Fi 密碼寫進公開的程式碼、截圖、作業或部落格;分享程式前,先改成提示文字或讀取本機設定檔。

三、讀懂 ifconfig() 回傳的資料

連線成功後,wlan.ifconfig()會回傳一組網路設定,依序包含 IP 位址、子網路遮罩、Gateway 與 DNS。可以先直接列印,再逐項辨認它們的用途。

if wlan.isconnected():
    ip_address, netmask, gateway, dns = wlan.ifconfig()

    print("IP address:", ip_address)
    print("Netmask:", netmask)
    print("Gateway:", gateway)
    print("DNS:", dns)
  • IP 位址:本例程式會顯示 Pico 實際取得的位址。位址可能因網路不同而改變,不要把課堂範例中的數字當成固定值。
  • Netmask:協助判斷哪些位址屬於同一個區域網路。
  • Gateway:通常是目前網路的路由器位址。
  • DNS:提供網域名稱查詢服務的伺服器位址。

多數教學環境會由 DHCP(動態主機設定協定)自動分配這些資訊。若沒有取得有效的網路設定,可能是連線尚未完成、基地台未提供位址,或該網路需要額外驗證。

四、掃描附近的 Wi-Fi 基地台

掃描可以幫助我們觀察 Pico 附近看得到哪些 AP,以及訊號強度等資訊。掃描只是在查看無線環境,不代表已經連上某個網路。

import network

wlan = network.WLAN(network.STA_IF)
wlan.active(True)

for ap in wlan.scan():
    print(ap)

每筆掃描結果會包含 SSID、基地台識別資訊、頻道、RSSI 訊號強度、安全模式與隱藏狀態等欄位;不同韌體的呈現形式可能略有差異。可比較同一地點不同 AP 的訊號,也可以移動 Pico 後重新掃描,觀察數值變化。

許多 IoT 開發板使用 2.4 GHz Wi-Fi。部署時要確認基地台提供裝置可用的頻段與安全設定;如果連不上,先檢查網路設備設定與課堂環境,不要直接推定是程式錯誤。

五、Pico 上不了網時,依序檢查

  1. 供電與 USB:確認 Pico 正常供電,Thonny 能和開發板互動。
  2. 基地台是否可見:執行掃描,確認目標網路出現在結果中。
  3. SSID 與密碼:檢查大小寫、空格與輸入內容;注意不要將密碼公開。
  4. Wi-Fi 是否已連線:以 wlan.isconnected()確認連線狀態。
  5. 是否取得網路設定:列印 wlan.ifconfig(),檢查 IP、Gateway 與 DNS。
  6. 是否能到達目標服務:依課堂允許的方式測試;校園網路可能限制 Ping 或其他連線方式。

每一步都記錄「成功到哪裡」,比反覆修改程式更容易找出問題。例如掃描看得到 AP、但無法連線,和已連線卻沒有取得 IP,代表問題可能在不同環節。

六、實作任務

  • 連上教師指定或自己建立的測試 Wi-Fi。
  • 列出附近 AP,觀察 SSID 與訊號強度。
  • 印出 Pico 的 IP、Netmask、Gateway 與 DNS。
  • 在程式中加入有限次數的重連嘗試,並顯示成功或失敗訊息。
  • 挑戰:設計一個 Wi-Fi 狀態 LED,讓不同連線狀態有可辨識的燈號。

記錄實驗時,可以保留程式、連線結果與除錯步驟;公開分享前,記得移除 Wi-Fi 密碼及其他帳號資訊。

本篇重點回顧

  • Wi-Fi 連線是加入無線區域網路,不等於一定能連上 Internet。
  • Pico 以 network.WLAN(network.STA_IF)連接既有基地台。
  • ifconfig()提供 IP、Netmask、Gateway 與 DNS 等設定。
  • 依照供電、掃描、帳密、連線狀態、IP 設定與服務可達性的順序除錯。
  • 不要將真實網路密碼放進公開程式碼或教材。

下一篇將從網路連線繼續前進,讓 Pico 2 W 建立 Web Server,並嘗試用瀏覽器與開發板互動。

Pico 2 W、Thonny 與 MicroPython 入門

Pico 2 W × Thonny|第 1 次課程

Pico 2 W、Thonny 與 MicroPython 入門

本篇從開發板、程式編輯環境與第一段 MicroPython 程式開始,帶你讓 Pico 2 W 控制 LED、讀取按鍵,建立「程式可以感知並控制真實世界」的第一個經驗。

作者:施朝斌

一、Pico 2 W 是什麼?

Pico 2 W 是一塊可程式化的微控制器開發板。它使用 RP2350 晶片,具備 GPIO 等硬體介面,並整合 Wi-Fi 與 Bluetooth 無線連線能力。課程後續會讓它連上網路,交換感測資料;不過在開始網路通訊以前,先熟悉程式如何和硬體互動,會更容易理解整套物聯網流程。

可以先把 Pico 2 W 想成一個小型「感測與控制節點」:感測器把環境變化交給它,程式依照輸入做判斷,再透過輸出控制 LED、馬達或其他裝置。第一堂先從 LED 和按鍵入手。

二、Thonny:編寫與執行 MicroPython 的工具

Thonny 是適合初學者使用的 Python 開發環境。連接 Pico 2 W 後,Thonny 的編輯區可用來撰寫程式,Shell 則能顯示執行結果、錯誤訊息,也能直接輸入指令測試。

1|選擇 Interpreter在 Thonny 的設定中選擇 Raspberry Pi Pico/MicroPython,以及正確的連接埠。
2|撰寫程式在編輯區輸入程式,先確認縮排與拼字。
3|執行與觀察按下 Run,觀察 Pico 上的 LED 或 Shell 輸出。
4|修正與儲存依結果調整程式;需要讓程式存於開發板時,可儲存為 main.py。

這個「修改、執行、觀察、修正」的循環,是初學程式很重要的工作方式。若 Thonny 無法連線,先檢查 USB 線、Interpreter 與連接埠是否選對,再查看 Shell 顯示的訊息。

三、第一個程式:讓板載 LED 閃爍

下面的程式會將 Pico 2 W 的板載 LED 設為輸出,並每隔半秒切換一次亮暗狀態。

from machine import Pin
import time

led = Pin("LED", Pin.OUT)

while True:
    led.toggle()
    time.sleep(0.5)

Pin("LED", Pin.OUT)代表以輸出方式控制板載 LED;while True讓程式持續重複執行;toggle()切換 LED 狀態;time.sleep(0.5)則暫停 0.5 秒。執行後若 LED 持續閃爍,就表示程式已成功控制硬體。

動手試試:將 0.5 改成 0.1 或 1,觀察閃爍速度如何改變。也可以挑戰「連閃三次,再停一秒」;先想清楚需要重複哪些動作,再修改程式。

四、從輸出到輸入:按鍵控制 LED

LED 是輸出裝置,按鍵則提供輸入。以下範例讀取接在 GPIO 15 的按鍵,再依照按鍵狀態控制 LED。

from machine import Pin

led = Pin("LED", Pin.OUT)
button = Pin(15, Pin.IN, Pin.PULL_UP)

while True:
    led.value(not button.value())

Pin(15, Pin.IN, Pin.PULL_UP)將 GPIO 15 設為輸入,並啟用內部上拉。使用上拉時,按鍵未按下的讀值通常為 1,按下後會變成 0;因此程式用 not 反轉讀值,讓按鍵按下時 LED 亮起。實際接線仍要依課堂使用的按鍵模組與電路圖確認,避免把電源與 GPIO 接錯。

這段程式呈現物聯網裝置的基本概念:程式讀取輸入,再控制輸出。日後把輸入換成溫度、水位或光線資料,再把結果送到網路,就能逐步建構感測應用。

五、認識常見硬體介面

  • GPIO:讀取或輸出數位訊號,例如按鍵、LED 或繼電器控制。
  • ADC:讀取類比電壓,可應用於光敏元件或電池電壓等情境。
  • PWM:以脈波方式控制輸出,常用於調整 LED 亮度或控制馬達。
  • I²C:讓控制板透過共同的通訊線路與多種數位感測器交換資料。

第一堂不必立刻精通所有介面。先知道它們各自能處理哪一類訊號,之後遇到感測器或控制任務時,就能選擇適合的連接方式。

六、第一堂實作任務

  1. 讓板載 LED 每秒閃爍一次。
  2. 使用按鍵控制 LED 亮起或熄滅。
  3. 按下按鍵時,讓 LED 快速閃爍。
  4. 記錄程式修改後的現象,並說明輸入、程式處理與輸出的關係。

完成後,學生不只看過程式碼,也已經讓程式和實體裝置互動。這是後續連線、建立 Web Server、使用 HTTP/JSON,以及透過 MQTT 傳送 IoT 資料的起點。

本篇重點回顧

  • Pico 2 W 是可透過程式讀取輸入、控制輸出的微控制器開發板。
  • Thonny 負責編寫、執行與除錯 MicroPython 程式。
  • GPIO 可設定為輸入或輸出;按鍵與 LED 是最容易觀察的練習組合。
  • 透過反覆修改、執行與觀察,逐步建立程式除錯能力。

下一篇將接續介紹 Pico 2 W 如何連上 Wi-Fi、查看網路資訊,並開始理解裝置如何進入 Internet。