然后是状态判断,有两种选择,1 是接同在前面板的 PWR LED,2 是接任意一个 +5V,但要保证独立于 +5VSB。比如 USB 就不太行,在有些时候关机是有电的。
所以初看起来 PWR LED 是个好选择,但问题是这一路的电阻并不能确定,导致电压可能介于 3V-5V 之间变化,我测量过我的主板,开机状态切断 LED 就是5V,连通降为 3V,是限流电阻的效果,但这也意味着落在 GPIO 输入上也会有一瞬间是5V,而原则上讲这不安全,反而要在稳压电路上动点心思了。再加一个降压模块有点难看,而且往往这东西会要求输入比输出至少高 1V,输入端降到 3V 左右的时候反而就失败了。
所以后来选择了和供电一起,直接从 ATX24针电源插头上偷电。
为什么要说“偷”电呢?。。。那个,我的意思是。。。窃电不能算偷。
知道公对母线的公头用在哪了吧-_-
一开始,我发现我的 USB 关机是有电的,所以把从前面板 USB 端口取电的排针都焊好了,然后我发现只要我是从 linux 系统关机的,USB 就没电了。。。这事居然还和 BIOS 设定无关,是 Windows10 的快速开机干出来的,我把这电源选项关了,然后关机连最后 1W 的耗电也没有了,同时 USB 就彻底关机无用了。
这使得我放弃了从 USB 取电的方法,转而动起了直接走电源的心思。不过这样很好,这个方法和主板/BIOS 无关,任何电源都是适用的。
macaddr=wifi.sta.getmac()
print('MAC Address: ',macaddr)
print('Chip ID: ',node.chipid())
print('Heap Size: ',node.heap(),'\n')
function createAP()
wifi.setmode(wifi.SOFTAP,false)
wifi.ap.config({ssid='NODEPCTR_'..string.sub(string.gsub(macaddr,':',''),7)},false)
wifi.ap.setip({ip='192.168.1.1',netmask='255.255.255.0',gateway='192.168.1.1'})
print("AP created.")
--5分钟后务必自动重启,防止和路由同时掉电后长期失联
tmr.create():alarm(300000, tmr.ALARM_SINGLE, function() node.restart() end)
end
netcfg=file.open('net.cfg')
if netcfg == nil then
createAP()
tmr.create():alarm(1000, tmr.ALARM_SINGLE, function() startServer() end)
else
local cfgitems={}
for cl in string.gmatch(netcfg:read(),'[%S]+') do table.insert(cfgitems,cl) end
netcfg:close()
ssid=cfgitems[1] wifipasswd=cfgitems[2]
mqttip=cfgitems[3] mqttport=cfgitems[4]
mqtopic=cfgitems[5]
tochkpwr=cfgitems[6]=='on' --使用GPIO3的判断条件,否则模块将失去调试及更新能力
wifi.setmode(wifi.STATION)
wifi.sta.config({ssid=ssid,pwd=wifipasswd})
wifi.sta.autoconnect(1)
print("Connecting to AP...")
tmr1=tmr.create()
wifiretries=5
tmr1:alarm(3000, tmr.ALARM_AUTO, function()
if wifi.sta.getip() ~= nil then
ip, nm, gw=wifi.sta.getip()
print("Connected using IP ",ip,'#',nm,'->',gw)
tmr1:unregister()
startServer()
else
wifiretries=wifiretries-1
if wifiretries <= 0 then
mqttip=''
createAP()
tmr1:unregister()
startServer()
end
end
end)
end
trigger_pin=4 --3=IO0,4=IO2,10=IO1/TX,9=IO3/RX
chkpw_pin=9
if tochkpwr then
gpio.mode(chkpw_pin,gpio.INPUT)
powstat = gpio.read(chkpw_pin)==gpio.HIGH and 'ON' or 'OFF'
print('Init Power is '..powstat)
end
pow_hold_time=200 --短按
powforce_hold_time=4500 --长按
gpio.mode(trigger_pin,gpio.INPUT)
tmr2=tmr.create()
function trigger_pow(force)
gpio.write(trigger_pin,gpio.LOW)
gpio.mode(trigger_pin,gpio.OUTPUT)
print("Relay on...")
ontime=tmr.now()
tmr2:alarm(force and powforce_hold_time or pow_hold_time, tmr.ALARM_SINGLE, function()
gpio.mode(trigger_pin,gpio.INPUT)
gpio.write(trigger_pin,gpio.HIGH)
el=(tmr.now()-ontime)/1000
print("Relay off in "..el.." ms.")
end)
end
configpage=string.format([[<!DOCTYPE html>
<html>
<head><meta charset="UTF-8" /><title>Network Config</title><style>label{display:inline-block;width:120px;}</style></head>
<body>
<form method="post" enctype="text/plain">
<label>MAC addr: </label>%s<br />
<label>SSID: </label><input type="text" name="ssid" value="%s" /><br />
<label>Password: </label><input type="text" name="pwd" value="%s" /><br />
<br />
<label>MQTT server: </label><input type="text" name="mqttip" value="%s" /><br />
<label>MQTT port: </label><input type="text" name="mqttport" value="%d" size="5" /><br />
<label>MQTT topic: </label><input type="text" name="mqtopic" value="%s" />(/ctrl)<br />
<label>Check Power: </label><input type="checkbox" name="chkpwr" value="on" /><br />
<br />
<input type="submit" value="Save" />
</form>
</body>
</html>]],macaddr,'','','',1883,'home/pc/id1')
function httpResponse(content,ctype,httpcode)
if ctype == 'html' then ctype = 'text/html; charset=UTF-8'
elseif ctype == 'text' or ctype == 'plain' then ctype = 'text/plain' end
return string.format([[HTTP/1.1 %s
Cache-Control: no-cache
Content-Type: %s
Content-Length: %d
%s]],httpcode or '200 OK',ctype or 'text/plain',#content,content)
end
function startServer()
srv=net.createServer(net.TCP,10)
srv:listen(80,function(conn)
conn:on("receive",function(conn,payload)
local _,ip = conn:getpeer()
local _,_,method,url = string.find(payload, '^([A-Z]+) (/%S+)')
print('['..ip..']',method,url)
if method ~= 'GET' and method ~= 'POST' then
print('Illegel request.')
conn:close()
return
end
if url == '/test' then
print("Interface test OK.")
conn:send(httpResponse("Interface test OK."))
elseif method == 'GET' and url == '/stat' then
conn:send(httpResponse(powstat or 'UNK'))
elseif method == 'POST' and url == '/pow' then
trigger_pow()
print("Power triggered.")
conn:send(httpResponse("OK"))
elseif method == 'POST' and url == '/powforce' then
trigger_pow(true)
print("Power triggered.")
conn:send(httpResponse("OK"))
elseif method == 'GET' and url == '/config' then
conn:send(httpResponse(configpage,'html'))
elseif method == 'POST' and url == '/config' then
local params={}
local _,cp=string.find(payload,'\r\n\r\n')
payload=string.sub(payload,cp+1)
for k,v in string.gmatch(payload,'(%w+)=([^%c]*)') do params[k]=v print(k,v) end
if params['ssid'] == nil or params['pwd'] == nil or params['ssid'] == '' or params['wifipasswd'] == '' then
conn:send(httpResponse('Wrong parameters.'),'plain','400')
else
file.open('net.cfg','w')
file.writeline(params['ssid']) file.writeline(params['pwd'])
file.writeline(params['mqttip'] or '') file.writeline(params['mqttport'] or '') file.writeline(params['mqtopic'] or '')
file.writeline(params['chkpwr'] or '')
file.close()
conn:send(httpResponse('Node is restarting.'))
tmr2:alarm(3000, tmr.ALARM_SINGLE, function() node.restart() end)
end
else
conn:send(httpResponse("ERROR",'404'))
end
end)
conn:on("sent", function(conn) conn:close() end)
end)
print('Server listening at port 80...')
if mqttip ~= nil and mqttip ~= '' then
mc=mqtt.Client('ESP'..node.chipid(),60)
mc:connect(mqttip,mqttport,false, function()
print('MQTT server connected.')
mc:subscribe(mqtopic..'/ctrl',0)
if powstat ~= nil then mc:publish(mqtopic,powstat,0,1) end
end)
mc:on("message", function(client,topic,message)
if message == 'pow' or message == 'powforce' then
trigger_pow(message=='powforce')
print("Power triggered.")
end
end)
end
if tochkpwr then
gpio.mode(chkpw_pin,gpio.INT)
gpio.trig(chkpw_pin,'both',function(level,when,ec)
powstat = gpio.read(chkpw_pin)==gpio.HIGH and 'ON' or 'OFF'
print('Power is '..powstat)
if mc ~= nil then mc:publish(mqtopic,powstat,0,1) end
end)
end
end