infinite loop さんが Crystal Signal Pi と言う製品を発売されました。Raspberry Pi を使った RGB color LED 信号灯です。これって NodeMCU で間に合うよね、と貧乏性なワタシです。当初は MicroPython で考えてみたものの、socket の非同期動作ができない(?)と言うことで不慣れな Lua で書いています。結局 socket の非同期処理とは関係なく、コマンドのパラメータをグローバルに置いてタイマで LED の点滅制御をしています。排他、それ何?みたいな雑なコードですみません。無駄に 100ms 毎にタイマ割込みを入れているのは PWM による LED の明るさ制御も自前でやってみようとした名残りです。
http://example.com//ctrl/?red=0&green=64&blue=255&period=500&rpt=300 のようににして使います。このパラメータ形式は当初の Crystal Sigal Pi の仕様にならったつもりなのですが、現行の仕様とは異なります。YouTubeにバラックで動作中の様子を置きました。
- MicroPython で web LED signal - MicroPython でも試してみました。(2017.01.27 追記)
websignal.lua
params = {red=0, green=0, blue=0, period=500, rpt=0}
ptimer = 0
power = false
pwm.setup(1, 500, 0) -- LED RED
pwm.setup(2, 500, 0) -- LED GREEN
pwm.setup(3, 500, 0) -- LED BLUE
pwm.start(1)
pwm.start(2)
pwm.start(3)
function split(str, pattern, n)
if not string.find(str, pattern) then
return { str }
end
local result = {}
local fpat = "(.-)" .. pattern
local insertCnt = 1
local lastEnd = 1
local s, e, cap = string.find(str, fpat, 1)
while s do
if insertCnt > n and n > 0 then
break
end
if s ~= 1 or cap ~= "" then
table.insert(result, cap)
end
insertCnt = insertCnt + 1
lastEnd = e + 1
s, e, cap = string.find(str, fpat, lastEnd)
end
if lastEnd <= #str then
cap = string.sub(str, lastEnd)
table.insert(result, cap)
end
return result
end
function pp()
local k, v
local s = ""
for k,v in pairs(params) do s = s.."<br>\n"..k..":"..v end
return s
end
function getparams(s)
local t = split(s, "\n", 2) -- get first line
t = split(t[1], " ", 4) -- get 'GET' argument
-- t[1]: s = "/ctrl/?red=0&green=64&blue=255&period=500&rpt=300"
t = split(t[2], "/", 2)
if not (#t > 1 and t[1] == 'ctrl' and string.sub(t[2], 1, 1) == '?') then
return false
end
tt = split(string.sub(t[2], 2), "&", 10)
local k, v
for k, v in pairs(tt) do
local a = split(v, "=", 2)
local k = a[1]
local v = a[2]
if params[k] ~= nil then
v = tonumber(v)
if v < 0 then v = 0 end
if k ~= 'period' and k ~= 'rpt' and v > 1023 then v = 1023 end
params[k] = v
end
end
print(pp())
tmfunc()
return true
end
function led(r, g, b)
print("R:"..r..",G:"..g..",B:"..b)
pwm.setduty(1, r)
pwm.setduty(2, g)
pwm.setduty(3, b)
end
function tmfunc()
local npower = power
if params['rpt'] > 0 then
if params['period'] == 0 then
npower = true
else
if ptimer > 0 then
ptimer = ptimer - 1
else
npower = not power
if not npower then params['rpt'] = params['rpt'] - 1 end
ptimer = params['period'] / 200
end
end
else
npower = off
end
-- LED on or off by params['power']
if power ~= npower then
power = npower
if power then led(params['red'], params['green'], params['blue']) else led(0, 0, 0) end
end
end
--
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID", "PASSWORD")
wifi.sta.autoconnect(1)
tmr.register(0, 100, tmr.ALARM_AUTO, function() tmfunc() end)
tmr.start(0)
srv=net.createServer(net.TCP)
srv:listen(80,
function(conn)
conn:on("receive",
function(conn,payload)
print(payload)
local r = getparams(payload)
if r then
conn:send("<h1>ESP8266 - Signal NodeMCU working!</h1><p>"..pp().."</p>")
else
conn:send("<h1>ESP8266 - Server is working!</h1><p>"..pp().."</p>")
end
conn:close()
end)
end)