超久々ですが、RaspberryPi Pico Wを入手できたため、micropythonにて公式サイトから拾えるraspberry-pi-pico-python-sdk.pdfにあるサンプルを参考にhttpサーバでLチカしてみました。 単にLチカしてもアレなので多少工夫を加えてあります
- Thonnyで開発したのですが、そのままだと再起動するたびにEADDRINUSEが出て引っこ抜く事になるためにsetsocketoptなどしてあります
- その他、丁寧にfinally節でcloseしてます
- ledピンはPin("LED", Pin.OUT)で得るのが無難なようです
- 何故かルータがいきなり初手でリクエストなしでアクセスしてきて開きっぱなしにするため、timeoutを付けました (不気味…)
- サーバっぽくos.fork()で処理したかったんだけどunixにしか無いんですなコレ…multiprocessingとかthreadはmicropythonで出来るのかどうか知らないので、手っ取り早くタイムアウトだけにしました
使い方は、本家のようにurlに/light/on で点灯、 /light/offで消灯ですが、それに加え、 /light/0x0f などとすると、8ビットの数値のビットパターンで、0だと「短く点灯」1だと「普通に点灯」で点滅により16進数を表現します。
さらに、/quitでサーバをシャットダウンしてwifiを切断します。
さすがmicroとはいえpythonだけあって色々簡単に出来て、面白いですね😆
なお、Thonnyでインタプリタを設定することでPico Wに直で開発中のコードを送り込んで実行することが可能なのですが、ubuntu 20.04.6で入るThonny 3.2.7にはPico Wの項目がありません…(当たり前かw)
しかしながら、これはesp32を指定すれば問題なく実行出来ました。まぁpythonだし大丈夫だろ…ということで😁
import network import socket import time import os from machine import Pin def send_response(cl, msg): global html response = html % msg cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n') cl.send(response) led = Pin("LED", Pin.OUT) ssid = 'your ssid' password = 'your password' wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) html = """<!DOCTYPE html> <html> <head> <title>Pico W</title> </head> <body> <h1>Pico W</h1> <p>%s</p> </body> </html> """ max_wait = 10 while max_wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break max_wait -= 1 print('waiting for connection...') time.sleep(1) if wlan.status() != 3: raise RuntimeError('network connection failed') else: print('connected') status = wlan.ifconfig() print( 'ip = ' + status[0] ) addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] s = socket.socket() s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # To avoid EADDRINUSE s.bind(addr) s.settimeout(5) # Some router accesses without request and connect forever. s.listen(1) print('listening on', addr) # Listen for connections unit = 0.5 # led blink unit in second try: while True: try: cl = None # for finally block. cl, addr = s.accept() print('client connected from', addr) ipaddr,port = addr print("waiting request...") request = cl.recv(1024) print(request) request = str(request) reqtail = request.find(' HTTP/1.1') if reqtail < 0: print("no request body") continue reqbody = request[6:reqtail].strip() print(reqbody) led_status = None if reqbody == '/quit': print("quit server.") send_response(cl, "Server shutdown.") break elif reqbody == '/light/on': led_status = True elif reqbody == '/light/off': led_status = False elif reqbody.startswith('/light/0x'): led_status = reqbody[7:11] if led_status is None: print("invalid request.") stateis = "invalid" elif led_status == True: led.value(1) stateis = "led on" elif led_status == False: led.value(0) stateis = "led off" else: # burst blink mode. try: value = int(led_status, 16) stateis = "blink : %s" % led_status for i in range(8): led.value(1) cv = (value >> i) & 1 if cv == 0: time.sleep(unit/3) else: time.sleep(unit) led.value(0) time.sleep(unit) except ValueError: stateis = "Failed to convert : %s" % led_status send_response(cl, stateis) except OSError as e: pass finally: if cl is not None: print('connection closed') cl.close() cl = None finally: s.close() wlan.disconnect()