2026年8月21日 星期五

聯網一下:從裝置、協定到智慧場域

大學部|網際網路系統整合與場域實作

聯網一下:
從裝置、協定到智慧場域

把ESP32、Wi-Fi、MQTT、HTTP、JSON、REST API、Django、Database與AI串成一個真正能運作、能診斷、能持續改善的智慧系統。

說得清架構寫得出協定找得到故障完成場域整合

會寫程式,還不等於會建構聯網系統

一段程式能在開發板上執行,只代表單一裝置可以工作。真正的智慧場域還需要考量裝置如何加入網路、訊息採用什麼格式、伺服器如何接收、資料如何保存,以及某一層失效時要從哪裡開始檢查。

大學部的網際網路課程,應從「使用網路」走向「設計網路服務」。學生不只要完成Demo,更要能解釋架構、驗證協定、診斷問題,並在真實場域中維持系統運作。

四項核心能力

① 說得清架構

說明Device、Edge、LAN、Internet、Cloud、Database與AI的責任邊界及資料流。

② 寫得出協定

能實作MQTT發布訂閱、HTTP Request、JSON Payload與REST API Endpoint。

③ 找得到故障

不把「不能用」當成單一問題,而是依Wi-Fi、DNS、TLS、API、Database逐層驗證。

④ 完成場域整合

把文化、養殖、農業或教育需求轉化為可操作、可監測、可維護的聯網服務。

智慧聯網五層架構

Layer 5|KnowledgeAI/RAG、決策服務把資料轉化成可理解、可檢索與可行動的知識
Layer 4|Cloud & DataDjango、API、Database、Dashboard接收、保存、查詢、視覺化與跨場次管理
Layer 3|NetworkWi-Fi、IP、DNS、HTTP/HTTPS、MQTT定義資料如何定址、傳輸及安全抵達
Layer 2|EdgeESP32 Edge Web、Gateway提供即時互動、離線能力與本地控制
Layer 1|Device感測器、按鈕、致動器、機器人把實體事件轉成數位資料,並把指令轉回動作

第一篇|說得清架構

從單一裝置走向端、邊、網、雲、智

學習重點:系統邊界、資料流、同步/非同步與服務責任。

以水井三寶智慧互動展覽系統為場域型專題教材

總整架構從ESP32、Edge Web、Internet、Django到AI/RAG。

一個按鈕按下後,資料去了哪裡?

資料流追蹤一筆事件從實體世界進入雲端資料庫。

ESP32同時當基地台又能上網:AP+STA

EdgeNetwork理解本地控制與Internet通道如何共存。

Machine Learning with Raspberry Pi 4 and Coral USB

Edge AI比較邊緣推論與雲端AI的角色及限制。

第二篇|寫得出協定

MQTT發布/訂閱與Topic
HTTP(S)Request/Response
JSON跨系統資料格式
REST API服務資源與Endpoint

讓不同設備與程式說同一種語言

學習重點:Topic、Method、Header、Body、Status Code與Payload驗證。

Raspberry Pi安裝MQTT之IoT應用-Arduino示範

MQTT從發布者、Broker、Topic到訂閱者建立基本模型。

利用ChatGPT產生發布MQTT主題的Python程式

AI協作MQTT產生程式後進行錯誤檢查、修改與驗證。

HTTP+JSON+REST API

HTTPJSONAPI理解「怎麼送、送什麼、送到哪個入口」。

ESP32 × Django REST API:將感測資料上傳雲端

HTTPS POST從ESP32送出JSON到Django Database與Dashboard。

第三篇|找得到故障

分層診斷順序

PowerWi-FiIPGatewayDNSTLSHTTP/MQTTAPIDatabase

「STA=ONLINE」只代表裝置加入Wi-Fi並取得IP,並不代表DNS、憑證、HTTPS、API及資料庫都已正常。每一層都要有可觀測證據。

用證據取代猜測

學習重點:Log、Status Code、Timeout、Retry、Queue與可觀測性。

IP、MAC、DNS、Domain與Port

定址診斷分辨裝置、服務名稱與Port之間的責任。

ESP32 AP+STA到Django雲端

分層除錯逐層檢查Wi-Fi、Gateway、DNS、TLS、HTTPS與Django。

在Home Assistant添加MQTT Broker並測試MQTT

Broker測試驗證連線、Topic與訊息收發。

Django+AJAX+JavaScript整合MQTT

前後端整合觀察訊息從Broker到網頁呈現的每個交界。

第四篇|完成場域整合

場域專題不是把技術堆在一起

學生要先界定使用者、情境與真實問題,再決定哪些資料值得感測、哪些反應必須留在Edge、哪些資料需要上Cloud,以及AI能否產生真正有用的知識。

文化展覽
按鈕/ToF → 故事播放 → Edge Web → Django事件 → AI導覽
智慧養殖
水溫/pH/DO/EC → HTTPS API → Dashboard → 異常判讀
農漁產銷
開放資料 → Django平台 → 市場圖表 → 電商與決策服務

可作為期末專題的場域文章

學習重點:需求分析、架構設計、整合驗證、成果展示與永續維運。

從Atlas Aquaponics Kit到Django雲端監控平台

智慧養殖多感測器、HTTPS POST、API、Database與Dashboard。

尚虎雲產銷平台助水井村智慧減碳節水三生一體

USRPBL從地方需求走向跨系統整合與永續服務。

Python/Django/PythonAnywhere實作農漁業交易行情

雲端資料整合開放資料、網站服務與產銷應用。

網際網路×USR:從地方故事到數位共生平台

服務設計思考系統為誰而做,以及如何持續被使用。

大學部成果評量

能力學生應完成成果證據
架構表達說明每一層的角色、責任邊界與資料流架構圖、資料流程圖、口頭簡報
協定實作完成MQTT或REST API收發,定義Payload與錯誤回應程式碼、API規格、測試紀錄
故障診斷用分層方法定位至少三種人為設定的故障Log、狀態碼、診斷報告
場域整合把裝置、Edge、Network、Cloud及Dashboard整合運作展示影片、系統網址、現場驗收
社會實踐說明使用者價值、資料倫理、隱私及維運方式需求訪談、風險檢核、維運計畫

真正的聯網能力,是讓系統在場域中持續運作

學生能寫出一段程式,只是開始;能把不同設備與服務整合、找出問題、提出證據並持續改善,才是大學部網際網路教育要培養的系統能力。

說得清架構・寫得出協定・找得到故障・完成場域整合

教材來源:智慧生活科技專業社群。本文依大學部網際網路、物聯網與智慧生活課程需求重新整理,可搭配PBL、CDIO、USR場域實作與期末系統驗收。

網路一下: 看得懂、連得上、做得出來

專科部|網際網路概論自主學習指南

網路一下:
看得懂、連得上、做得出來

從每天使用的手機與Wi-Fi出發,沿著一筆資料的旅行,認識IP、DNS、網站、雲端、物聯網與生成式AI,最後親手完成一個能真正上線的智慧應用。

👀 看得懂📡 連得上🛠️ 做得出來

網際網路,不只是「會上網」

我們每天傳訊息、看影片、搜尋資料、使用生成式AI,也可能用手機控制燈光、機器人與感測器。但是,按下按鈕之後,資料究竟去了哪裡?手機如何找到網站?為什麼同一台ESP32既能讓手機直接連線,又能把資料送到雲端?

這門課真正要學的,不是背完所有名詞,而是能把「裝置、網路、網站、資料與使用者」連成一條看得懂、查得到問題,也能動手完成的路徑。

三個學習目標

👀

看得懂

理解LAN、Internet、IP、MAC、DNS、Domain、Port、Client、Server及Cloud的角色,不再只記名詞。

📡

連得上

能設定Wi-Fi、辨認AP與STA、讀懂IP資訊,並用分層方法找出連線、DNS、HTTPS或API問題。

🛠️

做得出來

從HTML頁面開始,逐步完成Django網站、MQTT控制、REST API與智慧生活小專題。

先看懂:一筆資料如何旅行

  1. 使用者在手機或裝置上按下按鈕,產生一筆事件。
  2. 裝置透過Wi-Fi加入區域網路,由路由器取得IP位址。
  3. DNS把容易記憶的網域名稱轉換成伺服器IP。
  4. 瀏覽器或ESP32透過HTTP/HTTPS送出Request。
  5. 伺服器接收JSON資料,由Django程式處理並寫入Database。
  6. Dashboard把資料整理成圖表,AI再從資料中產生知識與建議。

單元一|看得懂網路的角色

從位址、名稱與服務入口,建立網際網路基本地圖。

IP、MAC、DNS、Domain與Port

CH01CH03理解「哪一台裝置、哪一個名稱、哪一項服務」。

一個按鈕按下後,資料去了哪裡?

CH01CH08用完整資料旅程串起抽象名詞。

Raspberry Pi應用之Windows檔案伺服器

CH04CH06理解Client/Server與網路資源分享。

當個快樂的物聯網自造者

CH08認識感測器、雲端、大數據與AI之間的關係。

再連上:從手機、Wi-Fi到Internet

單元二|讓裝置真正連得上

不只看到「已連線」,還要知道資料能不能抵達服務。

Raspberry Pi藍牙4.0應用之iBeacon發射器

CH02比較BLE、Wi-Fi、NFC及室內定位。

ESP32 Edge Web × 手機

CH04CH05手機直接連到小型Web Server。

ESP32同時當基地台又能上網:AP+STA

CH02CH04理解本地控制通道與Internet通道。

在Home Assistant添加MQTT Broker並測試MQTT

CH08以圖形化平台理解Broker、Topic與訊息傳遞。

最後做出來:網站、雲端、IoT與AI

單元三|完成可以展示的智慧應用

從一頁網站逐步走向雲端服務與智慧生活專題。

在PythonAnywhere設計Django網站的功能表

CH05建立網站頁面、URL與導覽結構。

在PythonAnywhere設計Django網站的輪播功能

CH05CH12結合內容設計與網站行銷。

在Django網站中設計登入功能

CH11CH13認識會員、Session及帳號安全。

Django登入功能加上圖形驗證

CH13從CAPTCHA理解網站的自動化攻擊防護。

好用的物聯網APP工具-IoT MQTT Panel

CH06CH08用手機完成物聯網發布、訂閱與控制。

Ollama和ChatGPT有何不同?

CH07CH09比較本地AI、雲端AI、隱私與成本。

HTTP+JSON+REST API

CH05CH08進一步理解網頁與雲端服務如何交換資料。

網際網路×USR:從地方故事到數位共生平台

CH11CH12思考網站為誰而做、解決什麼問題。

四項學習任務

任務一|畫出我的上網地圖從手機、AP、路由器、DNS到網站伺服器,畫出開啟網頁時資料經過的節點。
任務二|成為網路小偵探使用IP資訊與瀏覽器訊息,判斷問題發生在Wi-Fi、Gateway、DNS還是網站服務。
任務三|完成一頁地方網站用HTML或Django製作地方人物、文化、食農或工藝主題頁面。
任務四|讓實體事件上雲端讓按鈕、感測器或機器人透過MQTT或REST API把資料送到Dashboard。

學完之後,我可以做到什麼?

能力我能做到成果證據
網路理解用自己的話解釋IP、DNS、Domain、Port及Client/Server資料旅程圖、概念說明
連線診斷依序檢查Wi-Fi、IP、Gateway、DNS、HTTPS與服務狀態連線檢查表、除錯紀錄
網站製作完成具有導覽、圖片、內容及基本互動的網站網站網址、QR Code
智慧聯網讓手機、ESP32或感測器與雲端交換資料MQTT訊息、API紀錄、Dashboard
數位素養辨識密碼、個資、AI內容與著作權的基本風險風險檢核與使用說明

網路學習的終點,不是背出答案

而是面對一個真實需求時,知道資料從哪裡來、要往哪裡去、如何安全抵達,並能把技術做成真正有人願意使用的服務。

看得懂,是理解;連得上,是能力;做得出來,才是實踐。

教材來源:智慧生活科技專業社群。文章依專科部《網際網路概論》學習需求重新整理,實際授課時可搭配操作示範、學習單與場域型專題。

Python一下:從風土資料到智慧生活的程式設計

智慧生活科技專業社群|Python學習導航

Python一下:從風土資料到智慧生活的程式設計

從一隻會畫圖的海龜出發,走進百香果分級、中文檔案、小遊戲、網路資料與智慧物聯網。這不是文章清單,而是一條可以真正走完的Python學習路徑。

學Python不只是記住語法,而是學會把地方問題說清楚、把資料整理好,再讓程式替生活創造新的可能。

先看地圖:我現在應該學什麼?

第一次學習請由左至右;已有基礎者,可以直接從需要的主題開始。

STEP 1看見程式
輸出、Turtle、指令順序
STEP 2控制程式
變數、判斷、迴圈
STEP 3整理資料
List、Tuple、Set、Dict
STEP 4完成作品
函式、檔案、遊戲、IoT
學習方式:每篇文章都建議完成「先預測結果 → 親手輸入 → 修改一處 → 解釋差異」四個動作。不要只複製貼上,也不要只看AI的答案。

第一站|認識Python,讓程式動起來

打好Python程式基礎

入門Turtle函式

從畫線、長方形、正方形到星星,理解指令順序、迴圈與函式。

挑戰:改變顏色、角度與重複次數,創作自己的風土圖騰。

第二站|變數、判斷與迴圈

Python迴圈的美

基礎whileforif

以Turtle重複畫圓,比較逐行重複、whilefor及遞迴的不同寫法。

關鍵問題:同一個結果,為什麼可以有多種程式寫法?

Python雙迴圈基礎教材

基礎進階巢狀迴圈

從列與欄理解雙迴圈,建立圖形排列、座位表與二維資料的基礎。

挑戰:輸出實心方塊、空心方塊、三角形及棋盤圖案。

夠Python,九九乘法表

進階生成式join

將傳統雙迴圈改寫成串列生成式,體會精簡但仍須兼顧可讀性的Pythonic風格。

第三站|用風土資料學四大資料結構

當資料愈來愈多,重點不只是「存進去」,而是選擇最適合的資料結構。以下系列以百香果分級為共同情境。

資料結構生活比喻適用情形文章主題
List 串列可以調整順序的清單有順序、可重複、可修改從百香果分級看List串列
Tuple 元組公告後固定的標準有順序,但不希望被更改以Tuple表示百香果分級標準
Set 集合不重複的品項名單去除重複、交集與差集用Set進行百香果分級判斷
Dict 字典用等級查詢規格以鍵快速找到對應的值用Dict查詢百香果分級標準

前往「Python創新教材」彙整頁閱讀四篇文章 →

風土任務:將「百香果分級」改成雲林文旦、花生、烏魚子或水井村農漁產資料,並說明為什麼選擇這種資料結構。

第四站|函式:把解法變成可以重複使用的工具

函式不是為了把程式變難,而是替一段有意義的工作命名。建議回到「打好Python程式基礎」的繪圖程式,依序完成:

  1. 先寫出可以執行的重複指令。
  2. def將繪圖步驟包成函式。
  3. 加入長度、顏色、角度等參數。
  4. 讓函式回傳計算結果或執行狀態。
  5. 組合多個小函式,完成一個可測試的作品。
AI Pair任務:請AI提出重構建議,但學生必須逐項說明「修改了什麼、為什麼更好、測試結果為何」。

第五站|檔案與中文資料處理

檔案的簡易操作

基礎openUTF-8with

練習寫入、讀取、換行、中文編碼及with open()的安全寫法。

第六站|用小遊戲整合基本語法

用集合特性開發新版XAXB

程式重構Set生成式

比較2018與2019版本,觀察集合及生成式如何縮短程式。

Challenge AI:比較兩版的正確性、可讀性、效率及輸入例外。

第七站|從基本語法走向智慧生活

Python網路爬文

網路資料

讓Python從本機走向網路,取得可分析的公開資料。

micro:bit OLED初接觸

MicroPython硬體

把變數、迴圈及字串顯示在真實硬體上,感受程式與環境互動。

給學生的建議修課順序

階段學習內容代表文章學習成果
W1–W2動機、輸出、Turtle初遇Python、打好Python基礎完成風土圖騰
W3–W5變數、型別、判斷、迴圈變數是標籤、迴圈的美完成互動判斷程式
W6–W8雙迴圈、期中整合雙迴圈教材、九九乘法表完成圖形排列與解釋
W10–W12四大資料結構百香果List/Tuple/Set/Dict建立風土分級資料
W13–W14函式、檔案、例外檔案簡易操作、中文字數完成資料讀寫工具
W15–W17遊戲或智慧生活PBL猜數字、XAXB、UDP、micro:bit完成可展示專題
三層學習法:No-AI先獨立理解與手寫;AI Pair利用AI解釋、除錯及比較;Challenge AI則閱讀AI產生的程式,找錯、修改、設計測資並提出證據。

最後提醒:會執行,不等於會程式設計

真正的學習證據不是「畫面跑出來了」,而是能回答以下五個問題:

  1. 這段程式要解決什麼問題?
  2. 資料如何輸入、處理與輸出?
  3. 為什麼選擇這種流程或資料結構?
  4. 如果輸入錯誤或遇到邊界值,程式會怎樣?
  5. 你如何證明修改後的程式是正確的?

從風土資料出發,讓程式理解地方;從智慧生活出發,讓技術回到人的需要。

2026年8月20日 星期四

JQ6500 STOP 爆音除錯實錄

JQ6500 STOP 爆音除錯實錄

從「按 STOP 後無法續播」到 V1.8.8 Reset Only+Deferred Re-init

水井三寶智慧互動展覽系統|ESP32 × JQ6500 × Web Control × Debugging

在「水井三寶智慧互動展覽系統」中,JQ6500 負責播放白馬、烏龜、姻緣花等故事。系統原本在故事自然播放完畢後,可以正常切換到下一個故事;但只要使用手機 Web 按下 STOP,中途停止播放,再選另一個故事,就會出現「無法再次播放」的問題。更麻煩的是,後續雖然成功解決續播問題,STOP 時卻又出現明顯的「啵、啵」兩聲爆音。這篇文章完整記錄這次除錯過程,以及最後得到的工程經驗。

一、最初的問題:自然播完正常,STOP 後卻無法續播

最早觀察到的現象非常明確:

情況 A 白馬播放 ↓ 自然播放完畢 ↓ 再按烏龜 ↓ 正常播放 情況 B 白馬播放 ↓ 手機按 STOP ↓ 故事停止 ↓ 再按烏龜 ↓ 沒有正常播放 ↓ 必須斷電重開

這表示問題不在一般播放流程,而是在「人工中止」之後,JQ6500 的內部狀態沒有回到可重新播放的狀態。

二、第一個錯誤認知:把 0x0E 當成 STOP

早期程式使用:

0x7E, 0x02, 0x0E, 0xEF

原本把它命名為:

jqStop();

後來重新檢查指令語意後發現,0x0E 實際上是 PAUSE,不是真正的 STOP。這正好解釋為什麼人工停止後,播放器可能停留在 PAUSED 狀態,下一次使用 Play-by-index 指令時不一定能正常重新起播。

第一個重要經驗:
裝置通訊最怕「指令名稱寫得像真的」。如果函式叫 jqStop(),開發者很容易直接相信它就是 Stop,而忽略真正協定中的語意。

三、V1.8.5:改用 RESET 解決無法續播

後來改用 JQ6500 的 RESET 指令:

0x7E, 0x02, 0x0C, 0xEF

流程改成:

PAUSE ↓ RESET ↓ Select Flash ↓ Restore Volume ↓ READY

這一版最大的成果是:STOP 後終於可以正常再播放下一個故事。

但新的問題出現了:

按下 STOP 時,喇叭會明顯聽到「啵、啵」兩聲。

四、V1.8.6:先把音量設成 0,仍然沒有解決

第一個直覺是:會不會是 JQ6500 音量太大,所以 RESET 的瞬態被放大?

因此嘗試:

Volume → 0 ↓ Pause ↓ Reset ↓ Select Flash ↓ Restore Volume

程式另外設計了 Raw Volume Control,讓 STOP 過程中的暫時音量 0 不會改動手機設定,也不會寫入 NVS。

void jqSendVolumeRaw(uint8_t volume)
{
  // 只送命令
  // 不修改 currentVolume
  // 不寫入 NVS
}

但實測結果仍然是:

「啵、啵」兩聲依舊明顯。

這個結果非常重要,因為它告訴我們:問題不是數位音量參數本身。

五、V1.8.7:拿掉 PAUSE,只保留 RESET

接下來進一步做變因隔離。

如果兩聲分別是:

PAUSE → 啵 RESET → 啵

那拿掉 PAUSE 後,理論上應該只剩一聲。

因此 STOP 改成:

RESET ↓ Select Flash ↓ Volume = 0 ↓ Restore Volume

結果卻仍然是:

「啵、啵」兩聲。

這表示「第一聲=Pause、第二聲=Reset」這個推論並不成立。

六、V1.8.8:STOP 時真的只做 RESET

為了徹底排除後續初始化造成的影響,V1.8.8 採用最乾淨的實驗方式:

STOP 階段: RESET 0x0C ↓ jqNeedsRearm = true ↓ READY ★ 不 Select Flash ★ 不送 Volume=0 ★ 不 Restore Volume

真正的初始化全部延後到下一次使用者按 PLAY 時:

下一次 PLAY: 偵測 jqNeedsRearm ↓ Select Flash ↓ Restore Volume ↓ PLAY

這個版本有兩個重要結果:

測試項目結果
STOP 後再選下一個故事✅ 正常播放
STOP 當下爆音⚠️ 仍然是「啵、啵」兩聲

七、最後可以得到什麼結論?

經過 V1.8.5 → V1.8.8 的逐步排除,可以相當有把握地判斷:

這兩聲爆音不是 Web 控制、狀態機、NVS 音量、Select Flash 或 Restore Volume 造成,而是 JQ6500 在 RESET 過程中,內建 DAC/功放輸出級工作點改變所產生的硬體瞬態。

目前系統是 JQ6500 直接推喇叭,沒有使用外部功放:

JQ6500 │ SPK+ / SPK- │ ▼ Speaker

因此 RESET 時內部音訊級的關閉與重新建立偏壓,都直接反映到 Speaker 上。

八、為什麼會出現兩聲?

雖然 STOP 程式只有送一次 RESET,但 JQ6500 內部在 Reset 過程可能經歷:

內部功放 / DAC 關閉 ↓ 輸出工作點改變 ↓ 第一聲「啵」 ↓ 內部模組重新啟動 ↓ 偏壓重新建立 ↓ 第二聲「啵」

也就是說,兩聲未必需要兩個外部命令;一個 RESET 本身就可能包含兩個類比輸出瞬態。

九、這次除錯最重要的方法:一次只改一個變因

這次能真正找到原因,不是因為一次改很多程式,而是把可能因素逐步拆開:

版本STOP策略結果
V1.8.5Pause → Reset → Init可續播,但啵、啵
V1.8.6Volume 0 → Pause → Reset仍啵、啵
V1.8.7Reset → Init仍啵、啵
V1.8.8STOP 只 Reset;Init 延後到 PLAY仍啵、啵
第二個重要經驗:
除錯不是一直「加功能」,而是要有意識地做變因隔離。每一版只改一個關鍵行為,才能知道真正是哪一個因素造成結果。

十、什麼問題已經解決?什麼問題還沒解決?

項目目前狀態
自然播放完畢後再播下一首✅ 正常
手機中途 STOP✅ 正常停止
STOP 後再播下一首✅ V1.8.8 已正常
手機 Realtime Status✅ 正常
手機音量控制✅ 正常
音量寫入 NVS✅ 關機重開可保留
姻緣花 24 顆柔和彩虹旋轉✅ 正常
STOP 爆音⚠️ 還有「啵、啵」兩聲

十一、目前最合理的工程判斷

在功能已穩定的前提下,繼續修改 delay 或音量命令,效益已經很低。

目前最合理的判斷是:

V1.8.8 可視為目前穩定軟體版。

STOP 爆音屬於 JQ6500 直接驅動 Speaker 時,RESET 造成的類比輸出瞬態。若要完全消除,下一步應從硬體音訊架構處理,而不是持續修改 Web 或狀態機。

十二、未來真正要消除爆音,應該怎麼做?

如果正式展覽版要完全消除爆音,可以把音訊路徑改成:

JQ6500 DAC / Line Out ↓ 具有 MUTE / SHDN 的外部功放 ↓ Speaker

STOP 時先:

AMP MUTE ↓ JQ6500 RESET ↓ 等待穩定 ↓ AMP UNMUTE

這樣 JQ6500 即使仍然產生 RESET transient,也不會直接送到 Speaker。

目前尚未接外部功放,因此現階段不要誤以為「再加一個 delay」就能根治爆音。真正的解法應該是建立硬體 MUTE 點。

十三、這個案例對《網際網路應用》課程有什麼價值?

表面上看,這只是「STOP 後有爆音」的硬體問題;但實際上,它很適合讓學生理解完整系統除錯。

層級這次檢查的內容
Web手機是否真的送出 STOP Request
ESP32 ApplicationhandleStop() 與 State Machine 是否正確
UARTJQ6500 收到的是 Pause 還是 Reset
Device StateReset 後是否可以重新播放
Audio Hardware爆音是否來自 DAC/功放輸出瞬態

也就是說,一個看似簡單的 STOP 按鈕,其實橫跨:

Browser ↓ HTTP ↓ ESP32 Web Handler ↓ State Machine ↓ UART Command ↓ JQ6500 ↓ Audio Output ↓ Speaker

十四、從這次經驗學到的五件事

1. 指令語意一定要回到協定本身。
函式名稱叫 Stop,不代表實際送出的命令真的是 Stop。
2. 自然結束和人工中止,是兩條不同狀態路徑。
不能因為自然播放正常,就假設 STOP 後也會進入相同狀態。
3. 音量 0 不等於類比輸出真正靜音。
RESET 時 DAC/功放的工作點仍可能產生 transient。
4. 除錯要一次只改一個變因。
Pause、Reset、Volume、Select Flash、Restore Volume 必須逐項隔離。
5. 軟體問題解到最後,可能會證明其實是硬體特性。
這時應該停止一直改程式,改從系統架構處理。

十五、結語:失敗的版本也是教材

從 V1.8.5 到 V1.8.8,表面上像是在「反覆修改 STOP」,但真正累積的是一套非常有價值的工程判斷過程。

我們先解決「STOP 後不能再播放」,再逐步確認爆音不是音量、不是 Pause、不是 Select Flash、也不是重新初始化造成,最後把問題定位到 JQ6500 本身 RESET 時的音訊輸出瞬態。

真正有價值的不是某一版程式,而是知道:為什麼要改、改了什麼、結果如何、下一步該往哪裡查。

這也是「水井三寶智慧互動展覽系統」作為大學《網際網路應用》與 IoT 實作教材的重要價值:學生看到的不只是一個成功作品,而是一個真實系統如何一步一步從問題、測試、假設、修正走向穩定。

JQ6500 ESP32 STOP RESET UART Pop Noise Debugging Realtime Web IoT 水井三寶 USR

2026年8月18日 星期二

從接線施工到手機控制: 水井三寶 ESP32 擴充底板 × GPIO19 WS2812B × Web 音量控制實作

從接線施工到手機控制:
水井三寶 ESP32 擴充底板 × GPIO19 WS2812B × Web 音量控制實作

水井三寶智慧互動展覽系統|Layer 2~Layer 3 實作紀錄

ESP32 × WS2812B × JQ6500 × Edge Web × Realtime Status × Mobile Volume Control

「水井三寶智慧互動展覽系統」在實作過程中,除了要考慮程式能不能執行,更重要的是: 設備真正裝進展覽箱之後,好不好接線?好不好維修?現場人員能不能不用重新燒錄程式,就完成基本設定?

因此,本次系統在原有功能穩定之後,又進行兩項很重要的實務調整: 第一項是為了配合 ESP32 擴充底板與 WS2812B 三線式插頭,重新調整 LED DATA GPIO; 第二項則是在 V1.8 Realtime Web Status 基礎上加入手機音量控制,形成 Layer 4 V1.8.1「Realtime Status+Mobile Volume Control」

一、為什麼已經可以動了,還要修改GPIO?

早期測試 WS2812B 時,DATA 使用 GPIO13。從程式的角度來看完全沒有問題, 但當系統開始由麵包板實驗走向正式展覽箱施工時,問題就不再只是「GPIO能不能輸出」。

真正的問題變成:哪一支GPIO最適合施工?

  • 能不能直接配合擴充底板的三針插座?
  • 能不能使用現有 WS2812B 三線插頭?
  • 是否會和三顆實體按鈕衝突?
  • 是否會影響 JQ6500 UART?
  • 日後拆裝與維修是否方便?

二、從 GPIO13 改成 GPIO19

經過重新檢查擴充底板可使用的腳位後, GPIO19 可以直接配合板上的插座,而且不需要搬動目前已經測試穩定的按鈕與 JQ6500 接腳, 因此最後決定:

WS2812B DATA:GPIO13 → GPIO19
功能 GPIO 說明
白馬按鈕 GPIO32 維持原接線
烏龜按鈕 GPIO33 維持原接線
姻緣花按鈕 GPIO25 維持原接線
JQ6500 UART GPIO26 / GPIO27 已完成穩定測試,不再更動
ToF VL53L0X GPIO21 / GPIO22 I2C SDA / SCL
WS2812B DATA GPIO19 配合擴充底板三針插座

三、程式其實只需要改一個地方

這正是軟硬體模組化的好處。 LED控制邏輯沒有改變,只是將資料輸出的GPIO重新指定。

原來版本

#define LED_PIN 13

新版

#define LED_PIN 19

Adafruit NeoPixel 的初始化方式仍然相同:

#define LED_PIN    19
#define LED_COUNT  61

Adafruit_NeoPixel strip(
  LED_COUNT,
  LED_PIN,
  NEO_GRB + NEO_KHZ800
);
這次修改的重要經驗:
GPIO選擇不能只從「程式能不能跑」來思考。 當作品進入正式施工階段,還要把接頭、底板、線材、維修方式與模組位置一起納入設計。

四、WS2812B 如何接到 ESP32 擴充底板?

WS2812B 基本上需要三條線:

ESP32 擴充底板 GPIO19 / Signal │ ├────────────→ WS2812B DIN │ 5V / VCC ├────────────→ WS2812B +5V │ GND └────────────→ WS2812B GND

如果 LED 數量較多,正式展覽系統建議讓 WS2812B 使用獨立 5V 電源, ESP32只提供 DATA,但兩邊的 GND 必須共地。

ESP32 GPIO19 ─────────→ WS2812B DIN 外接 5V + ───────────→ WS2812B +5V 外接 5V GND ─────┬───→ WS2812B GND │ ESP32 GND ────────┘ 必須共地
施工注意: 三針插頭的線色不能直接當成腳位依據, 一定要確認擴充板的 Signal / VCC / GND, 以及 WS2812B 的 DIN / 5V / GND 順序。

五、61顆WS2812B不是只拿來「發亮」

目前系統將 61 顆 WS2812B 分成不同區域:

#define BASE_START       0
#define BASE_COUNT       9

#define HORSE_START      9
#define HORSE_COUNT     16

#define TURTLE_START    25
#define TURTLE_COUNT    12

#define FLOWER_START    37
#define FLOWER_COUNT    24
區域 LED數量 燈光意義
底座 9 系統基礎氛圍
白馬 16 行動、力量、向前
烏龜 12 水、生態、守護
姻緣花 24 祝福、緣分、生命與地方情感

尤其姻緣花已由原本的固定色彩改成 HSV 彩虹色, 讓不同 LED 呈現五顏六色的效果,再搭配逐漸綻放與收縮的動畫。

uint16_t hue =
  colorOffset +
  (65535UL * i / FLOWER_COUNT);

strip.setPixelColor(
  FLOWER_START + i,
  strip.gamma32(
    strip.ColorHSV(
      hue,
      255,
      100
    )
  )
);

因此燈光不只是裝飾,而是成為展覽系統的一種 視覺回饋介面

六、第二個問題:展場音量不能每次都重新燒錄

JQ6500 原本的音量是在 Arduino 程式中設定:

uint8_t currentVolume = 20;

JQ6500 的控制範圍設定為:

0 ~ 30

如果要從 20 改成 25 或 30,最簡單的方法當然是修改程式再重新燒錄。 但是到了真正的展覽現場,這種方式非常不方便。

不同場域需要不同音量:
  • 安靜教室可能只需要 15~20。
  • 兒童館可能需要 20~25。
  • 大型展覽空間可能需要更高音量。
  • 閉館測試時可能希望立即靜音。

因此 V1.8.1 的設計目標很直接:

讓手機成為水井三寶的音量遙控器。

七、V1.8.1:手機直接控制 JQ6500 音量

手機連上 ESP32 的:

Wi-Fi SSID: Shuijing-Treasures ↓ 瀏覽器 ↓ http://192.168.4.1

就可以在 Edge Web 控制頁看到:

🔊 音量控制

0 ─────────── ● ─────────── 30

目前音量:20 / 30

【靜音】 【15】 【20】 【25】 【最大30】

八、HTML使用 Range Slider

Web介面使用 HTML 的 range 元件:

<input
  type="range"
  id="volumeSlider"
  min="0"
  max="30"
  value="20"
>

這讓手機可以直接拖曳調整:

0 ↓ 5 ↓ 10 ↓ 15 ↓ 20 ↓ 25 ↓ 30

九、手機不是直接控制JQ6500

這一點非常適合拿來作為《網際網路應用》課程教材。

手機調整音量時,真正的資料流程是:

手機瀏覽器 │ │ HTTP Request ▼ ESP32 Edge Web │ │ /volume?v=25 ▼ Web Handler │ ▼ jqSetVolume(25) │ │ UART Command ▼ JQ6500 │ ▼ 喇叭音量改變

也就是:

Web介面 → HTTP → ESP32 → UART → JQ6500 → 喇叭

十、Web端如何送出音量設定?

JavaScript 可以使用 fetch()

async function setVolume(v)
{
  const r = await fetch(
    '/volume?v=' + encodeURIComponent(v),
    {
      cache:'no-store'
    }
  );

  const d = await r.json();

  document.getElementById(
    'volumeValue'
  ).textContent = d.volume;
}

例如使用者選擇 25,瀏覽器送出:

GET /volume?v=25

十一、ESP32如何接收?

ESP32 Web Server 收到 /volume Request 後, 讀取參數並限制在 0~30:

int volume =
  server.arg("v").toInt();

if (volume < 0)
{
  volume = 0;
}

if (volume > 30)
{
  volume = 30;
}

jqSetVolume(
  (uint8_t)volume
);

完成後再回傳 JSON:

{
  "ok": true,
  "volume": 25
}

十二、為什麼回傳JSON,而不是重新整理網頁?

早期 Web 控制很容易採用:

按按鈕 ↓ ESP32執行 ↓ Redirect ↓ 整個網頁重新載入

V1.8.1 則改成:

拖曳音量 ↓ fetch() ↓ /volume?v=25 ↓ ESP32設定JQ6500 ↓ 回傳JSON ↓ 只更新音量數字

因此操作更接近現代 Web App, 也不會因為每次調整音量就讓整個手機畫面閃動。

十三、V1.8的重要改進:Realtime Web Status

在早期版本中曾經出現一個很有意思的問題:

故事已經播放完畢,ESP32 Serial Monitor 也顯示 PLAY COMPLETE, 但是手機網頁仍然顯示:

PLAYING

原因不是 JQ6500,也不是 ESP32 狀態機, 而是瀏覽器看到的是載入網頁那一刻的狀態。

因此 V1.8 新增:

/api/status

手機每秒讀取一次最新狀態:

setInterval(
  updateStatus,
  1000
);

十四、Realtime Status與音量控制整合

V1.8.1 再把音量加入 Status JSON。 概念上可以得到:

{
  "state":"PLAYING",
  "story":"白馬故事",
  "jq_busy":true,
  "volume":25,
  "cloud_ok":18,
  "cloud_fail":0
}

因此手機控制頁可以同時知道:

  • 現在是不是正在播放。
  • 目前播放哪一個故事。
  • JQ6500 BUSY 是否有效。
  • 目前音量是多少。
  • ESP32目前的即時狀態。

十五、播放完成後,手機會自己變化

現在操作流程變成:

手機按下「白馬」 ↓ PLAYING 白馬故事 JQ BUSY:ACTIVE ↓ 語音播放完成 ↓ COOLDOWN 白馬故事 JQ BUSY:IDLE ↓ 約2秒 ↓ READY / IDLE 待機

使用者不再需要手動按「重新整理」。

十六、為什麼Status Polling不能算成「使用者操作」?

這是 V1.8 開發過程中另一個很重要的系統設計問題。

水井三寶採用:

Local First, Cloud Later
現場互動優先,雲端同步延後。

如果瀏覽器每秒查詢 /api/status, ESP32每次都把它當成「使用者正在操作」, Cloud Sync 就可能永遠等不到真正的 Idle 時間。

因此:

void handleStatus()
{
  // 不呼叫 markLocalActivity()

  ...
}

也就是把:

「查詢狀態」 和 「真正操作設備」 分開處理。

十七、V1.8.1的完整控制關係

手機 │ │ Wi-Fi ▼ ESP32 Edge Web 192.168.4.1 │ ┌─────────┼─────────┐ │ │ │ ▼ ▼ ▼ 故事控制 音量控制 即時狀態 /play /volume /api/status │ │ ▲ ▼ ▼ │ ESP32 ────────────────┘ │ ├──── UART ───→ JQ6500 ───→ 喇叭 │ ├──── GPIO19 ─→ WS2812B │ ├──── I2C ────→ VL53L0X │ └──── Wi-Fi STA │ ▼ Internet │ ▼ Django / Cloud

十八、從「接腳修改」看工程設計

GPIO13改成GPIO19,看起來只修改了一行程式:

#define LED_PIN 19

但背後其實代表系統已經從:

「麵包板能動」 進入 「正式作品能施工」 再進入 「現場人員能維護」

這也是 IoT 專題很重要的一課: 好的系統不只是功能正確,也要考慮安裝、操作與維護。

十九、從「音量控制」看Edge Web的價值

同樣地,音量原本只是 Arduino 裡的一個變數:

uint8_t currentVolume = 20;

但是加入 Edge Web 之後, 這個變數就成為使用者可以透過手機操作的系統參數。

Arduino Variable currentVolume ↓ ESP32 Web API /volume?v=25 ↓ HTML / JavaScript Volume Slider ↓ 手機操作介面

這就是 Edge Web 很重要的價值:

把嵌入式系統內部的控制功能, 轉換成一般使用者也能操作的 Web 服務。

二十、從水井三寶學「網際網路應用」

這次修改雖然從「換一支GPIO」和「增加音量滑桿」開始, 但其實可以串起很多《網際網路應用》的重要概念。

實作 可以學到的概念
GPIO19控制WS2812B Embedded I/O、硬體介面、模組化設計
手機連ESP32 SoftAP、Wi-Fi、IP、Client / Server
192.168.4.1 Private IP、Edge Web Server
/volume?v=25 URL、Path、Query Parameter、HTTP GET
fetch() 非同步Web Request
JSON Response Web資料交換格式
/api/status API、Realtime Status、Polling
JQ6500 UART、裝置控制
WS2812B 數位燈光與視覺回饋
Django同步 Edge → Internet → Cloud

二十一、版本演進

版本 主要功能
早期版本 ESP32+JQ6500基本故事播放
Layer 3 ESP32 Edge Web手機控制
Layer 4 V1.7 AP+STA+Django+Queue+Cloud Sync
Layer 4 V1.8 Realtime Web Status
Layer 4 V1.8.1 Realtime Status+Mobile Volume Control+GPIO19 WS2812B施工配置

二十二、結語:真正的IoT,是讓實體作品、網路與使用者連在一起

水井三寶智慧互動展覽系統的開發不是一次完成, 而是在實際接線、播放、展示、手機操作與雲端同步的過程中不斷修正。

從 GPIO13 改成 GPIO19, 是為了讓硬體更適合正式施工; 從固定音量改成手機控制, 是為了讓系統更適合真實展覽環境; 從靜態網頁改成 Realtime Status, 則是讓使用者真正看見設備當下的狀態。

文化作品是起點,ESP32負責互動,Edge Web負責控制, Internet負責連結,Django負責資料,而未來的AI/RAG則負責讓地方知識持續被理解與使用。

這也正是「水井三寶智慧互動展覽系統」作為 大學《網際網路應用》與USR實作教材最重要的價值: 不是只教學生把程式寫出來,而是讓學生從一個真實地方文化作品出發, 一路理解硬體、網路、Web、資料與使用者之間如何形成一個完整系統。

水井三寶 ESP32 GPIO19 WS2812B JQ6500 Edge Web Realtime Status Mobile Volume Control HTTP JSON IoT Django USR

2026年8月16日 星期日

以「水井三寶智慧互動展覽系統」為場域型專題教材

網際網路應用|課程大綱

以「水井三寶智慧互動展覽系統」為場域型專題教材

ESP32 → Edge Web → Internet → Django → Data → Knowledge → AI/RAG

模組名稱智慧生活與物聯網
課程名稱網際網路應用
計畫名稱水井村智慧減碳節水三生一體實踐計畫

一、課程簡介

本課程以「水井三寶智慧互動展覽系統」作為《網際網路應用》的場域型專題教材,將抽象的網路協定、位址、Client/Server、Web API與雲端資料概念,轉化為學生可以看見、操作、量測與除錯的真實系統。學生從白馬、烏龜、姻緣花三項地方文化作品出發,理解按鈕、感測器、JQ6500語音與WS2812B燈光如何由ESP32控制;再以手機連入ESP32 Edge Web,實際觀察AP、STA、IP、MAC、DNS、Domain、Port及HTTP Request的作用;進一步將匿名互動事件以JSON及REST API送往Django,建立Digital Twin、資料庫與雲端儀表板。課程不以「會做網頁」為終點,而是追問「一個按鈕按下後,資料去了哪裡?」讓學生沿著實體互動、區域網路、Internet、Web Server、API、Database一路追蹤資料生命週期。最後再由Data走向Knowledge與AI/RAG,思考地方故事如何被整理為可搜尋、可引用、可延伸的文化知識。藉由水井村USR真實場域,學生不只學習網際網路技術,也理解科技如何服務文化保存、地方教育與大學社會責任,培養需求分析、系統整合、網路診斷與知識應用能力。

二、課程核心問題

一個按鈕按下後,資料去了哪裡? ↓ ESP32 → Edge Web → Wi-Fi → IP / DNS → HTTP / JSON / REST API ↓ Django → Database → Digital Twin ↓ Data → Knowledge → AI/RAG

三、學習目標

  • 理解ESP32與周邊裝置通訊,以及實體事件如何轉為數位資料。
  • 理解AP、STA、LAN、IP、MAC、DNS、Domain、Port等網路概念。
  • 理解Browser、Client、Server、Edge Web及HTTP資料流程。
  • 理解GET/POST、Header、Body、JSON與REST API。
  • 將ESP32匿名事件送至Django,理解Database與Dashboard。
  • 能以分層方法診斷Wi-Fi、DNS、HTTPS、API與Cloud問題。
  • 理解Data、Knowledge與AI/RAG的關係。
  • 從USR場域需求思考網際網路技術的社會實踐價值。

四、五層架構與課程主軸

層級系統角色課程重點
Layer 1|文化作品層白馬、烏龜、姻緣花需求、情境、實體與數位系統邊界
Layer 2|智慧互動層ESP32+ToF+按鈕+JQ6500+RGBGPIO、UART、事件、裝置控制
Layer 3|Edge Web層ESP32內嵌網站AP/STA、IP、Web Server、HTTP
Layer 4|Digital Twin / Data層Django+Database+DashboardDNS、HTTPS、JSON、REST API、資料庫
Layer 5|文化知識層文化網站+AI/RAGData → Knowledge、RAG、知識服務

五、系列教材文章

#教材主題核心概念文章連結
1ESP32 × JQ6500 UART 通訊UART序列通訊、語音模組、封包命令閱讀教材
2Layer 2|智慧互動層GPIO、按鈕事件、JQ6500故事播放、互動狀態閱讀教材
3Layer 3|ESP32 Edge WebWeb Server、HTTP、手機控制、192.168.4.1、Edge Computing閱讀教材
4Layer 4|ESP32 × DjangoClient/Server、HTTP、Django、事件資料、Digital Twin閱讀教材
5ESP32 AP+STA 共存SoftAP、Station、LAN與Internet、本地控制與雲端連線閱讀教材
6Layer 4 V1.7|AP+STA+Django整合實測Wi-Fi診斷、DNS、HTTPS、Queue、Local First / Cloud Later閱讀教材
7水井三寶智慧互動展覽系統|五層架構文化作品、智慧互動、Edge Web、Digital Twin/Data、文化知識閱讀教材
8WS2812B × ESP32 燈光控制RGB LED、單線數位控制、色彩編碼、故事狀態回饋閱讀教材
9一個按鈕按下後,資料去了哪裡?Browser → Edge → HTTP → JSON → Django → Database → Dashboard閱讀教材
10IP、MAC、DNS、Domain與PortMAC、IP、Gateway、DNS、Domain、Port、網路診斷閱讀教材
11Data → Knowledge → AI/RAG事件資料、文化知識庫、Chunk、Metadata、Embedding、Vector Search、RAG閱讀教材
12HTTP+JSON+REST APIGET/POST、Header、Body、JSON、REST Endpoint、HTTP Status、Django API閱讀教材

六、建議學習路徑

裝置通訊:ESP32 × JQ6500 × WS2812B ↓ 智慧互動:按鈕 / 感測 → 故事 → 狀態 ↓ Edge Web:手機 → AP → 192.168.4.1 → HTTP ↓ 網路基礎:AP / STA → MAC → IP → Gateway → DNS → Domain → Port ↓ Internet應用:HTTP → JSON → REST API → HTTPS ↓ Cloud / Data:Django → Database → Dashboard → Digital Twin ↓ Knowledge / AI:Data → Knowledge Base → Retrieval → AI/RAG

七、從「做作品」轉向「理解系統」

本課程不把Arduino程式、ESP32接線或Django網站視為彼此獨立的單元,而是要求學生追蹤一筆資料的完整旅程。學生不只要知道「程式可以跑」,還要能回答:手機為什麼找到192.168.4.1?ESP32為什麼同時需要AP與STA?Domain如何透過DNS找到Server?JSON如何進入HTTP Body?Django為什麼回201?當Cloud HTTP=-1時,問題究竟發生在Wi-Fi、DNS、TLS還是API?

核心教學觀念:會使用網路工具只是起點;能畫出資料流、說明協定角色、判斷故障所在層級,才是真正理解「網際網路應用」。

八、USR × 網際網路應用

水井三寶讓網際網路課程不再只是虛擬案例。學生面對的是地方文化作品、展覽觀眾、現場網路、設備可靠度與文化知識保存等真實需求。技術因此不只是完成作業,而是成為連結地方故事、智慧互動、教育推廣與資料累積的工具。透過場域實作,學生可以理解大學社會責任不只是「到社區服務」,而是運用專業知識與地方共同解決問題,並留下可以持續運作、持續學習與持續擴充的系統。

九、關鍵字

ESP32IoTEdge WebAP / STAIP / MAC / DNSHTTPJSONREST APIDjangoDigital TwinAI/RAGUSR

[水井村USR] HTTP+JSON+REST API

HTTP+JSON+REST API

從「水井三寶智慧互動展覽系統」看懂ESP32如何把資料送到Django

HTTP Request × Header × JSON Body × REST Endpoint × Django API × Response

當ESP32已經能連上Internet,下一個問題就是:它到底如何把「烏龜故事被播放」這件事送到Django?答案不是單靠Wi-Fi,而是透過HTTP、JSON與REST API三個重要概念協同工作。這篇文章就用水井三寶Layer 4的資料流,帶學生看懂一筆匿名事件如何從ESP32送到雲端。

一、先從一筆事件開始

{
  "event_uuid":"SHUIJING-001-0000000062",
  "event_type":"STORY_START",
  "story":"002",
  "source":"web",
  "duration_ms":0,
  "completed":null,
  "network_status":"online",
  "metadata":{
    "firmware":"Layer4-V1.7",
    "jq_confirmed":true
  }
}

這段資料本身還沒有「送上網」。它只是ESP32中的一個JSON字串。接下來才輪到HTTP與REST API登場。

二、HTTP是什麼?

HTTP可以理解成Client與Server之間溝通的規則。水井三寶同時用到GET與POST:

Method水井三寶例子用途
GET/play?track=2手機要求ESP32播放烏龜故事
POST/api/exhibition/events/ESP32把匿名事件送到Django
一句話記:GET常用來取得資源或提出查詢;POST常用來把資料送給Server處理。

三、一個HTTP Request有哪三個部分?

Request Line POST /api/exhibition/events/ HTTP/1.1 Headers Content-Type: application/json X-Device-ID: SHUIJING-001 X-Device-Key: ******** Body { "event_type":"STORY_START", "story":"002" }
部分作用
Request Line使用什麼Method、要去哪一個Path
Headers提供內容格式、裝置識別、驗證資訊
Body真正要送給Server的資料

四、JSON是什麼?

JSON是一種文字格式,適合不同系統之間交換結構化資料。

{
  "story":"002",
  "source":"web",
  "completed":true
}
KeyValue意義
story"002"烏龜故事
source"web"由Edge Web啟動
completedtrue故事完整播放
JSON的價值:ESP32、JavaScript、Python、Django等平台都可以很容易解析,因此非常適合IoT與Web API。

五、為什麼要寫 Content-Type?

Content-Type: application/json

這一行是在告訴Django:「這次HTTP Body裡裝的是JSON。」如果Server不知道資料格式,就無法正確解析內容。

六、REST API是什麼?

REST API是一種設計Web服務的方式:把系統功能整理成清楚的URL Endpoint,再搭配HTTP Method進行操作。

https://shuijingtreasures.pythonanywhere.com/api/exhibition/events/
https:// 安全的HTTP通訊 shuijingtreasures.pythonanywhere.com Domain / Server /api/exhibition/events/ REST API Endpoint
Endpoint可以理解成「API的入口地址」。

七、為什麼ESP32不能直接呼叫Django函式?

ESP32和Django位於不同設備、不同執行環境,因此ESP32不能直接執行Server上的Python函式,只能透過網路把Request送到URL,再由Django URL Router找到對應View。

ESP32 ↓ HTTP POST /api/exhibition/events/ ↓ Django URL Router ↓ api_event() ↓ Database

八、Device ID與API Key放在哪裡?

X-Device-ID: SHUIJING-001
X-Device-Key: ********

它們放在HTTP Header,讓Django知道是哪一台設備,以及這台設備是否有權限傳送資料。

正式API Key不應公開放在部落格、簡報或公開GitHub倉庫。教材只示範格式即可。

九、ESP32端的HTTP POST概念

WiFiClientSecure client;
HTTPClient https;

https.begin(
  client,
  "https://shuijingtreasures.pythonanywhere.com/api/exhibition/events/"
);

https.addHeader(
  "Content-Type",
  "application/json"
);

https.addHeader(
  "X-Device-ID",
  DEVICE_ID
);

https.addHeader(
  "X-Device-Key",
  DEVICE_KEY
);

int code = https.POST(jsonBody);
建立HTTPS Client ↓ 指定REST API URL ↓ 加入Headers ↓ 放入JSON Body ↓ POST ↓ 等待HTTP Response

十、Server如何告訴ESP32成功或失敗?

Status Code常見意義
200Request成功
201資料建立成功
400Request內容有問題
401驗證失敗
404API路徑不存在
500Server內部錯誤

水井三寶Cloud Test成功時,可看到:

Cloud HTTP = 201
Response = {"ok":true,...}
CLOUD POST OK

這代表DNS、HTTPS、API URL、裝置驗證與Django資料接收都已經成功。

十一、為什麼 Cloud HTTP = -1 不是Django回的狀態碼?

實作過程中曾出現:

Cloud HTTP = -1

後來追查發現問題發生在DNS解析階段,也就是HTTP Request根本還沒到Django。

DNS失敗 ↓ 找不到Server IP ↓ 無法建立TCP/TLS連線 ↓ HTTP Request沒有到Django ↓ 自然也不會有401 / 404 / 500
除錯原則:Cloud失敗時,不要第一時間就修改Django;先確認Wi-Fi、DNS、TLS與HTTP是否真的走到Server。

十二、為什麼採用 Local First, Cloud Later?

如果每次故事一開始就同步做HTTPS POST,可能讓JQ6500播放、Edge Web與網路傳輸互相干擾。因此系統採取:

故事播放 ↓ 建立JSON Event ↓ 先存LittleFS Queue ↓ 播放完成 ↓ 系統空閒 ↓ HTTP POST ↓ Django
設計原則:現場互動優先;雲端同步延後。

十三、HTTP、JSON、REST API怎麼分工?

技術主要工作水井三寶角色
HTTP規定Client與Server怎麼請求與回應ESP32 POST事件到Django
JSON描述資料格式故事、來源、完成狀態等事件內容
REST API定義Server提供的URL服務入口/api/exhibition/events/
一句話記:HTTP是「怎麼送」,JSON是「送什麼」,REST API是「送到哪個功能入口」。

十四、一筆「烏龜故事」事件的完整旅程

使用者按「002 烏龜故事」 ↓ ESP32 Edge Web ↓ JQ6500開始播放 ↓ 建立 JSON ↓ LittleFS Queue ↓ ESP32 STA ↓ DNS找到PythonAnywhere ↓ HTTPS ↓ POST /api/exhibition/events/ ↓ Headers:Device ID / API Key ↓ JSON Body ↓ Django View ↓ Database ↓ HTTP 201 Response ↓ Dashboard

十五、和水井三寶五層架構的關係

層級HTTP / JSON / REST API的角色
Layer 2 智慧互動層產生故事與感測事件
Layer 3 Edge Web層本地HTTP GET控制ESP32
Layer 4 Digital Twin / Data層HTTP POST+JSON+REST API送到Django
Layer 5 文化知識層未來可透過API提供文化內容與AI/RAG服務

十六、真正理解API,要能回答七個問題

Client是誰? ESP32 Server是誰? Django Protocol? HTTPS Endpoint? /api/exhibition/events/ Method? POST 資料格式? JSON 成功如何判斷? HTTP Status + Response Body

十七、課堂思考題

問題一:如果JSON格式正確,但API URL打錯,可能得到哪一類HTTP狀態?
問題二:為什麼Device ID與API Key適合放Header,而故事內容放Body?
問題三:GET與POST都能帶資料,為什麼事件上傳通常選POST?
問題四:如果Django已回201,但Dashboard沒有資料,問題可能已經移到哪一層?

十八、結語:REST API是Edge與Cloud之間的橋

水井三寶的ESP32負責感測、故事播放與現場控制,Django負責跨場次資料、Dashboard與後續分析。兩邊位於不同設備、使用不同語言,卻能透過HTTP+JSON+REST API協同工作。

因此,REST API真正重要的地方,不只是讓ESP32「可以傳資料」,而是建立清楚的系統邊界:Edge負責即時互動,Cloud負責資料服務。HTTP定義溝通方式,JSON定義資料語言,而REST API定義雙方合作的入口。

HTTP GET POST JSON REST API Endpoint Header HTTPS ESP32 Django