M5Stampの続き。
今回もサンプルプロジェクトから。
やりたいこと
前にM5StampでWi-Fiが使えることが確認できたので、サーバー機能を入れたりして、子供のおもちゃをIoT化したときの機能の一つとして使いたい。
サンプルプロジェクト確認
サンプルプロジェクトの中に、http_serverがある。これを使ってみたい。
http_serverの中にもサンプルが色々あるが、simpleを使ってみる。
HTTP基本
その前にHTTPがよくわかっていないので調べる。
とりあえずこのあたりのサイトで、HTTPの簡単な中身。
2つ目のサイトは、更新日不明だが、"1998年現在"とか書いてあったりしてかなり古めだが、Google検索で上のほうに来てたので、今でも参考になるということか。
プロジェクト作成、ビルド、実行
今までの手順通り。
- "ESP-IDF: Set Espressif device target"でターゲットを"esp32c3"に設定。
- "ESP-IDF: Select port to use (COM, tty, usbserial)"でデバイス接続したCOMポートを指定。(デバイス接続しておく必要がある)
- "ESP-IDF: Select Flash Method"で、書き込み方法を"UART"に指定。
- "ESP-IDF: SDK Configuration editor"でプロジェクト設定。
Example Configurationを見ると、WiFi SSIDとパスワードの設定あり。
"Get ssid and password from stdin"で、stdinからSSIDとパスワード設定もできるようなので、これを試してみる。
- "Save"して、"ESP-IDF: Build, Flash and start a monitor on your device"でビルドと実行。
実行
実行すると、ターミナルウィンドウに、SSIDとパスワード入力を求める表示が出るので、入力。
なんだかうまくつながらなかったようで、"Wi-Fi disconnected, trying to reconnect..."が何回か出て、自分で再起動したよう。
最終的に、同じSSID、パスワード入力画面になった。
ここでのSSID、パスワードの入力のしかたがよくわからなかったが、結局SSIDの後にスペースを一度入力して、続けてパスワードを入力したらつながった。
接続後、IPを取得(192.168.1.11)してポート80にサーバーが立ち上がったよう。
クライアント側からテスト
テスト方法
READMEを見ると、pythonでscripts/client.pyを実行する、curlコマンドを使う、という2つのテスト方法が書かれている。
前者は、スクリプトで全部勝手にやると何が起こっているかわかりにくそうだし、そもそもscripts/client.pyがどこにいるかもよくわからない。
ので、後者のcurlコマンド実行するほうで。
curlコマンドでテスト
PowerShellでcurlコマンド使えるのかよくわからないが、やってみる。
(base) PS C:\work\esp-idf_test\simple_httpd_server\simple> curl 192.168.1.11:80/hello StatusCode : 200 StatusDescription : OK Content : Hello World! RawContent : HTTP/1.1 200 OK Custom-Header-1: Custom-Value-1 Custom-Header-2: Custom-Value-2 Content-Length: 12 Content-Type: text/html Hello World! Forms : {} Headers : {[Custom-Header-1, Custom-Value-1], [Custom-Header-2, Custom-Value-2], [Content-Lengt h, 12], [Content-Type, text/html]} Images : {} InputFields : {} Links : {} ParsedHtml : System.__ComObject RawContentLength : 12 (base) PS C:\work\esp-idf_test\simple_httpd_server\simple>
できた。HTTPの中身が確認できる。
このときのM5Stamp側の出力はこんな感じ。
I (324197) example: Found header => Host: 192.168.1.11 I (324197) example: Request headers lost
ここでは、HTTPのGETメソッドを実行することができた。
その他試してみたり調べたりして分かったこと。
- PowerShellでは、
Invoke-WebRequest
コマンドレットでHTTPリクエストを出せるとのこと - さっきやった感じ、PowerShellでも
curl
コマンドが使えたっぽかったが、Invoke-WebRequest
へのエイリアスとして設定されているだけとのこと。
Invoke-webRequestとcurlコマンドでHTTPリクエスト | SugiBlog
実際、PowerShellで、curl
でのPOSTメソッドをやってみようとしたが、ダメだった。引数のフォーマットが違うからではないかと思われる - 今使ってるPCにgitをインストールしたときにbashもセットアップされていて、こっちで
curl
コマンドを使うことはできた。 Invoke-WebRequest
とcurl
では実行結果の表示に違いあり。
色々実行結果
PowerShell(Invoke-WebRequest
) or bash(curl
)、GETメソッド or POSTメソッドの組み合わせで試してみた。
PowerShell、GETメソッド
PowerShellでcurl
コマンドを打ったときと同じ結果になった。
(base) PS C:\work\esp-idf_test\simple_httpd_server\simple> Invoke-WebRequest 192.168.1.11:80/hello StatusCode : 200 StatusDescription : OK Content : Hello World! RawContent : HTTP/1.1 200 OK Custom-Header-1: Custom-Value-1 Custom-Header-2: Custom-Value-2 Content-Length: 12 Content-Type: text/html Hello World! Forms : {} Headers : {[Custom-Header-1, Custom-Value-1], [Custom-Header-2, Custom-Value-2], [Content-Lengt h, 12], [Content-Type, text/html]} Images : {} InputFields : {} Links : {} ParsedHtml : System.__ComObject RawContentLength : 12
M5Stamp側。当然こちらも同じ。
I (133427) example: Found header => Host: 192.168.1.11 I (133427) example: Request headers lost
PowerShell、POSTメソッド
curl
コマンドだと、ファイルを送る例がプロジェクトのREADMEに書かれていたが、Invoke-WebRequest
の場合のやり方がわからなかった。適当な文字列を送っている。
(base) PS C:\work\esp-idf_test\simple_httpd_server\simple> Invoke-WebRequest -Method POST -Body @{key="tekitou"} 192.168.1.11:80/echo StatusCode : 200 StatusDescription : OK Content : key=tekitou RawContent : HTTP/1.1 200 OK Transfer-Encoding: chunked Content-Type: text/html key=tekitou Forms : {} Headers : {[Transfer-Encoding, chunked], [Content-Type, text/html]} Images : {} InputFields : {} Links : {} ParsedHtml : System.__ComObject RawContentLength : 11
M5Stamp側。
I (822307) example: =========== RECEIVED DATA ========== I (822307) example: key=tekitou I (822307) example: ====================================
bash、GETメソッド
a@dell MINGW64 /c/work/esp-idf_test/simple_httpd_server/simple $ curl 192.168.1.11:80/hello Hello World!
必要最小限の結果表示になった。
-v
オプションで、もう少し経過が表示される。
知っておくとちょっと便利!curl コマンドの使い方をご紹介 | SIOS Tech. Lab
a@dell MINGW64 /c/work/esp-idf_test/simple_httpd_server/simple $ curl 192.168.1.11:80/hello -v * Trying 192.168.1.11:80... * Connected to 192.168.1.11 (192.168.1.11) port 80 (#0) > GET /hello HTTP/1.1 > Host: 192.168.1.11 > User-Agent: curl/8.1.2 > Accept: */* > < HTTP/1.1 200 OK < Content-Type: text/html < Content-Length: 12 < Custom-Header-1: Custom-Value-1 < Custom-Header-2: Custom-Value-2 < Hello World!* Connection #0 to host 192.168.1.11 left intact
Invoke-WebRequest
の結果と似ているが、もう少し時系列的な情報が出ているよう。
M5Stamp側は特に表示は変わらない。
I (1053277) example: Found header => Host: 192.168.1.11 I (1053287) example: Request headers lost
bash、POSTメソッド
bashでは、ファイルの中身を送ることができた。
プロジェクト内の適当なファイル(main/CMakeLists.txt)を送ってみた。
a@dell MINGW64 /c/work/esp-idf_test/simple_httpd_server/simple $ curl -X POST --data-binary @main/CMakeLists.txt 192.168.1.11:80/echo set(requires "") if(${IDF_TARGET} STREQUAL "linux") list(APPEND requires esp_stubs esp-tls esp_http_server protocol_examples_common nvs_flash) endif() idf_component_register(SRCS "main.c" INCLUDE_DIRS "." REQUIRES ${requires})
echoのところに送っているが、送った内容がそのまま返されている。今回はファイルの中身。
上と同様に、-v
オプションで詳細が表示される。
a@dell MINGW64 /c/work/esp-idf_test/simple_httpd_server/simple $ curl -X POST --data-binary @main/CMakeLists.txt 192.168.1.11:80/echo -v Note: Unnecessary use of -X or --request, POST is already inferred. * Trying 192.168.1.11:80... * Connected to 192.168.1.11 (192.168.1.11) port 80 (#0) > POST /echo HTTP/1.1 > Host: 192.168.1.11 > User-Agent: curl/8.1.2 > Accept: */* > Content-Length: 278 > Content-Type: application/x-www-form-urlencoded > < HTTP/1.1 200 OK < Content-Type: text/html < Transfer-Encoding: chunked < set(requires "") if(${IDF_TARGET} STREQUAL "linux") list(APPEND requires esp_stubs esp-tls esp_http_server protocol_examples_common nvs_flash) endif() idf_component_register(SRCS "main.c" INCLUDE_DIRS "." REQUIRES ${requires}) * Connection #0 to host 192.168.1.11 left intact a@dell MINGW64 /c/work/esp-idf_test/simple_httpd_server/simple $
M5Stamp側。
I (1376567) example: =========== RECEIVED DATA ========== I (1376567) example: set(requires "") if(${IDF_TARGET} STREQUAL "linux") list(APPEND requires esp_stubs esp-tls esp I (1376577) example: ==================================== I (1376577) example: =========== RECEIVED DATA ========== I (1376587) example: _http_server protocol_examples_common nvs_flash) endif() idf_component_register(SRCS "main.c" I (1376597) example: ==================================== I (1376597) example: =========== RECEIVED DATA ========== I (1376607) example: INCLUDE_DIRS "." REQUIRES ${requires}) I (1376627) example: ====================================
いくつかにデータが区切られて送られている。
参考: M5Stamp出力全部
一応載せておく。
何度かM5Stamp上での実行をやり直していて、最終的にうまくできたときのログ出力になっている。
クリックで開く/閉じる
(base) PS C:\work\esp-idf_test\simple_httpd_server\simple> set IDF_PATH=C:\Users\a\esp\esp-idf (base) PS C:\work\esp-idf_test\simple_httpd_server\simple> c:\work\esp-idf_env\.espressif\python_env\idf5.1_py3.11_env\Scripts\python.exe C:\Users\a\esp\esp-idf\tools\idf_monitor.py -p COM3 -b 115200 --toolchain-prefix riscv32-esp-elf- --target esp32c3 c:\work\esp-idf_test\simple_httpd_server\simple\build\simple.elf --- WARNING: GDB cannot open serial ports accessed as COMx --- Using \\.\COM3 instead... --- esp-idf-monitor 1.3.3 on \\.\COM3 115200 --- --- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- ESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT) SPIWP:0xee mode:DIO, clock div:1 load:0x3fcd5820,len:0x1704 load:0x403cc710,len:0x968 load:0x403ce710,len:0x2f68 entry 0x403cc710 I (30) boot: ESP-IDF v5.1.1 2nd stage bootloader I (30) boot: compile time Nov 14 2023 06:54:17 I (30) boot: chip revision: v0.3 I (33) boot.esp32c3: SPI Speed : 80MHz I (38) boot.esp32c3: SPI Mode : DIO I (43) boot.esp32c3: SPI Flash Size : 2MB I (47) boot: Enabling RNG early entropy source... I (53) boot: Partition Table: I (56) boot: ## Label Usage Type ST Offset Length I (64) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (71) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (79) boot: 2 factory factory app 00 00 00010000 00100000 I (86) boot: End of partition table I (90) esp_image: segment 0: paddr=00010020 vaddr=3c0a0020 size=237c8h (145352) map I (122) esp_image: segment 1: paddr=000337f0 vaddr=3fc91600 size=02854h ( 10324) load I (124) esp_image: segment 2: paddr=0003604c vaddr=40380000 size=09fcch ( 40908) load I (135) esp_image: segment 3: paddr=00040020 vaddr=42000020 size=97adch (621276) map I (235) esp_image: segment 4: paddr=000d7b04 vaddr=40389fcc size=07518h ( 29976) load I (246) boot: Loaded app from partition at offset 0x10000 I (247) boot: Disabling RNG early entropy source... I (258) cpu_start: Unicore app I (258) cpu_start: Pro cpu up. I (267) cpu_start: Pro cpu start user code I (267) cpu_start: cpu freq: 160000000 Hz I (267) cpu_start: Application information: I (270) cpu_start: Project name: simple I (275) cpu_start: App version: 1 I (279) cpu_start: Compile time: Nov 14 2023 06:53:57 I (285) cpu_start: ELF file SHA256: 3b03a5999661a97d... I (291) cpu_start: ESP-IDF: v5.1.1 I (296) cpu_start: Min chip rev: v0.3 I (301) cpu_start: Max chip rev: v0.99 I (306) cpu_start: Chip rev: v0.3 I (310) heap_init: Initializing. RAM available for dynamic allocation: I (318) heap_init: At 3FC97F20 len 000447F0 (273 KiB): DRAM I (324) heap_init: At 3FCDC710 len 00002950 (10 KiB): STACK/DRAM I (331) heap_init: At 50000010 len 00001FD8 (7 KiB): RTCRAM I (338) spi_flash: detected chip: generic I (341) spi_flash: flash io: dio W (345) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (359) sleep: Configure to isolate all GPIO pins in sleep state I (365) sleep: Enable automatic switching of GPIO sleep configuration I (373) app_start: Starting scheduler on CPU0 I (377) main_task: Started on CPU0 I (377) main_task: Calling app_main() I (387) example_connect: Start example_connect. I (387) pp: pp rom version: 9387209 I (387) net80211: net80211 rom version: 9387209 I (407) wifi:wifi driver task: 3fca08fc, prio:23, stack:6656, core=0 I (407) wifi:wifi firmware version: ce9244d I (407) wifi:wifi certification version: v7.0 I (407) wifi:config NVS flash: enabled I (417) wifi:config nano formating: disabled I (417) wifi:Init data frame dynamic rx buffer num: 32 I (417) wifi:Init management frame dynamic rx buffer num: 32 I (427) wifi:Init management short buffer num: 32 I (427) wifi:Init dynamic tx buffer num: 32 I (437) wifi:Init static tx FG buffer num: 2 I (437) wifi:Init static rx buffer size: 1600 I (447) wifi:Init static rx buffer num: 10 I (447) wifi:Init dynamic rx buffer num: 32 I (447) wifi_init: rx ba win: 6 I (457) wifi_init: tcpip mbox: 32 I (457) wifi_init: udp mbox: 6 I (467) wifi_init: tcp mbox: 6 I (467) wifi_init: tcp tx win: 5744 I (467) wifi_init: tcp rx win: 5744 I (477) wifi_init: tcp mss: 1440 I (477) wifi_init: WiFi IRAM OP enabled I (487) wifi_init: WiFi RX IRAM OP enabled I (487) phy_init: phy_version 970,1856f88,May 10 2023,17:44:12 I (537) wifi:mode : sta (68:67:25:b2:53:44) I (537) wifi:enable tsf I (537) example_connect: Please input ssid password: I (82457) example_connect: Connecting to XXXXXXXXXXXXX... I (82457) example_connect: Waiting for IP(s) I (84867) wifi:new:<5,0>, old:<1,0>, ap:<255,255>, sta:<5,0>, prof:1 I (85547) wifi:state: init -> auth (b0) I (85547) wifi:state: auth -> assoc (0) I (85557) wifi:state: assoc -> run (10) I (85567) wifi:connected with XXXXXXXXXXXXX, aid = 12, channel 5, BW20, bssid = 48:3e:5e:7c:4a:53 I (85567) wifi:security: WPA2-PSK, phy: bgn, rssi: -63 I (85577) wifi:pm start, type: 1 I (85577) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000 I (85587) wifi:AP's beacon interval = 102400 us, DTIM period = 1 I (86717) wifi:<ba-add>idx:0 (ifx:0, 48:3e:5e:7c:4a:53), tid:6, ssn:1, winSize:64 I (87387) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:6a67:25ff:feb2:5344, type: ESP_IP6_ADDR_IS_LINK_LOCAL I (87597) esp_netif_handlers: example_netif_sta ip: 192.168.1.11, mask: 255.255.255.0, gw: 192.168.1.1 I (87597) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.1.11 I (87607) example_common: Connected to example_netif_sta I (87617) example_common: - IPv4 address: 192.168.1.11, I (87617) example_common: - IPv6 address: fe80:0000:0000:0000:6a67:25ff:feb2:5344, type: ESP_IP6_ADDR_IS_LINK_LOCAL I (87627) example: Starting server on port: '80' I (87637) example: Registering URI handlers I (89487) wifi:<ba-add>idx:1 (ifx:0, 48:3e:5e:7c:4a:53), tid:0, ssn:1, winSize:64 I (133427) example: Found header => Host: 192.168.1.11 I (133427) example: Request headers lost I (243947) example: =========== RECEIVED DATA ========== I (243947) example: foo=main%2FCMakeLists.txt I (243947) example: ==================================== I (822307) example: =========== RECEIVED DATA ========== I (822307) example: key=tekitou I (822307) example: ==================================== I (1053277) example: Found header => Host: 192.168.1.11 I (1053287) example: Request headers lost I (1150567) example: Found header => Host: 192.168.1.11 I (1150567) example: Request headers lost I (1376567) example: =========== RECEIVED DATA ========== I (1376567) example: set(requires "") if(${IDF_TARGET} STREQUAL "linux") list(APPEND requires esp_stubs esp-tls esp I (1376577) example: ==================================== I (1376577) example: =========== RECEIVED DATA ========== I (1376587) example: _http_server protocol_examples_common nvs_flash) endif() idf_component_register(SRCS "main.c" I (1376597) example: ==================================== I (1376597) example: =========== RECEIVED DATA ========== I (1376607) example: INCLUDE_DIRS "." REQUIRES ${requires}) I (1376627) example: ==================================== I (1515027) example: =========== RECEIVED DATA ========== I (1515027) example: set(requires "") if(${IDF_TARGET} STREQUAL "linux") list(APPEND requires esp_stubs esp-tls esp I (1515037) example: ==================================== I (1515047) example: =========== RECEIVED DATA ========== I (1515057) example: _http_server protocol_examples_common nvs_flash) endif() idf_component_register(SRCS "main.c" I (1515067) example: ==================================== I (1515067) example: =========== RECEIVED DATA ========== I (1515077) example: INCLUDE_DIRS "." REQUIRES ${requires}) I (1515087) example: ====================================
以上
サーバー機能使えそうなことは分かったが、HTTPとかもうちょっと勉強しないとできないかもしれない。
まだまだM5Stamp色々いじってみたい。