1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
local wakeup = require("+wakeup")
--- Builds and returns a Wake-on-LAN magic packet for [[mac]] address.
local
function magic_packet (mac)
local data = ""
for octet in mac:gmatch("%x%x") do
data = data .. string.char(tonumber(octet, 16))
end
if #data ~= 6 then
error(string.format("Invalid MAC\t%q", mac), 2)
end
return string.char(0xff):rep(6) .. data:rep(16)
end
function wakeup:open ()
self.udp = net.createUDPSocket()
end
function wakeup:close ()
if self.udp then
self.udp:close()
end
end
--- Creates a new counter that has :up() method that returns true until it gets called N [[times]]. Then it returns only
--- false.
local
function new_counter (times)
return {
count = 0,
times = times,
up = function (self)
self.count = self.count + 1
return self.count <= self.times
end,
}
end
--- Begins to send Wake-on-LAN magic packets to the broadcast [[.addr]] for selected [[.mac]]. Packets are sent several
--- [[times]] each separated by [[interval]]. Callback is called [[after]] all packets are sent.
function wakeup:sendout (interval, times, after)
self:open()
local count = new_counter(times)
return tmr.create():alarm(interval, tmr.ALARM_SEMI, function (timer)
if count:up() then
print("Waking up", self.mac, self.addr)
self.udp:send(self.port, self.addr, self.data)
timer:start()
else
timer:unregister()
self:close()
after()
end
end)
end
function wakeup:now ()
local time = rtctime.epoch2cal(rtctime.get())
time.year = nil
time.sec = nil
return time
end
local
function compare (time, pattern)
for key, value in pairs(pattern) do
if time[key] ~= value then
return false
end
end
return true
end
function wakeup:init ()
gpio.write(4, gpio.HIGH)
gpio.mode(4, gpio.OUTPUT)
self.data = magic_packet(self.mac)
wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function ()
sntp.sync(
self.sntp,
function ()
if compare(self:now(), self.when) then
gpio.write(4, gpio.LOW)
self:sendout(500, 5, function ()
wifi.setmode(wifi.NULLMODE, false)
gpio.write(4, gpio.HIGH)
end)
else
print("Not yet time")
wifi.setmode(wifi.NULLMODE, false)
tmr.create():alarm(25000, tmr.ALARM_SINGLE, function ()
self:run()
end)
end
end,
function (code, err)
print("SNTP sync failed", code, err)
node.restart()
end)
end)
end
function wakeup:run ()
wifi.setmode(wifi.STATION, false)
wifi.sta.connect()
end
return wakeup
|