MicroPython で web LED signal

このプログラムは前に書いた [NodeMCU で web LED signal](http://qiita.com/n24bass/items/bc96baaaad7359dca9bc) の MicroPython 版です。処理内容はほぼ同じで新たなリクエストがあると現在の処理をキャンセルします。点滅の間隔を直接タイマの設定値にしている点が異なります。元の Lua のコードは PWM もタイマ処理でしようかと考えていた名残りで無駄に何度もタイマ割込みをしていたのを止めました。

この MicroPython 実装では一旦ステーションモードでアクセスポイントに接続すると、その接続情報を記憶してリセット後にも自動的に接続を試行します。また、アクセスポイントモードでも動作しています。その辺は適当に制御が必要でしょう。

[YouTube](https://www.youtube.com/watch?v=48F32NLfHhA)の動画も更新しました。

```python:SignalPy.py
#  SignalPy.py
#  usage: http://hostname:8080/ctrl/?red=50&green=255&blue=255&period=500&repeat=300

import utime as time
import usocket as socket
from machine import Timer, Pin, PWM

ESSID = 'your ESSID'
PASS = 'your password'
PORT = 8080

# LED parameters
param = {
    'red': 0,
    'green': 0,
    'blue': 0,
    'period': 0,
    'repeat': 0,
    }
tim = Timer(-1)
power = False

led_r = PWM(Pin(5, Pin.OUT, value = 0), freq = 512, duty = 0)
led_g = PWM(Pin(4, Pin.OUT, value = 0), freq = 512, duty = 0)
led_b = PWM(Pin(0, Pin.OUT, value = 0), freq = 512, duty = 0)

def tmfunc(*args):
    global param, power
    npower = power
    if param['repeat'] > 0:
        npower = not power
	if not npower:
            param['repeat'] = param['repeat'] - 1
    else:
        npower = False

    if power != npower:
        power = npower
        led(power)
        
def do_connect():
    import network
    # -- ESP8266 as station mode
    # sta_if = network.WLAN(network.STA_IF)
    # if not sta_if.isconnected():
    #     print('connecting to network...')
    #     sta_if.active(True)
    #     sta_if.connect(ESSID, PASS)
    #     while not sta_if.isconnected():
    #         pass
    # cf = sta_if.ifconfig()
    # -- ESP8266 as access point mode
    ap_if = network.WLAN(network.AP_IF)
    cf = ap_if.ifconfig()
    # --
    print('network config:', cf)
    return cf[0]

def parser(s):
    try:
        r = s.split('/')
        if r[1] != 'ctrl' or len(r) < 3 or r[2][0] != '?' : return
        p = dict([i.split('=') for i in [i for i in r[2][1:].split('&')]])
        print("params:",p)
        global param        # print("\nperser({0})".format(s), r)
        for i in ['red', 'green', 'blue', 'period', 'repeat']:
            max_value = 1023 if i in ['red', 'green', 'blue'] else 60000
            try:
                param[i] = min(int(p.get(i)), max_value)
            except:
                param[i] = 0
        tim.deinit()
        led(False)
        if param['period'] > 0:
            tim.init(period = param['period'], mode = Timer.PERIODIC, callback = tmfunc)
    except:
        pass

def led(sw):
    if sw:
        print("o\010", end="")
        led_b.duty(param['blue'])
        led_r.duty(param['red'])
        led_g.duty(param['green'])
    else:
        print("-\010", end="")
        led_b.duty(0)
        led_r.duty(0)
        led_g.duty(0)

# ------------

CONTENT = """\
HTTP/1.0 200 OK

Hello #{} from MicroPython!
"""

ip = do_connect()
ai = socket.getaddrinfo(ip, PORT)
addr = ai[0][4]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(addr)
s.listen(5)
counter=0

while True:
    res = s.accept()
    print("accept")
    client_s = res[0]
    client_addr = res[1]
    print("Client address:", client_addr)
    print("Client socket:", client_s)
    req = client_s.recv(1024)
    print("Request=", req)
    client_s.send(bytes(CONTENT.format(counter), "ascii"))
    parts = req.decode('ascii').split(' ')
    if len(parts) > 0:
        if parts[1] == '/exit':
            client_s.close()
            break
        parser(parts[1])
        client_s.send(bytes("valid param: {0}\n\n".format(param), "ascii"))
    else:
        client_s.send("invalid param {0}".format(req), "ascii")
    client_s.close()
    counter += 1

# ------------

```