summaryrefslogtreecommitdiff
path: root/run.lua
blob: 3c22c309d44bac286a30a19508979f16e0773cf6 (plain)
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
local wol = {
	port = 9,
	timer = tmr.create(),
}


--- Reads configuration file at [[path]] and parses a pair of MAC and broadcast addresses from it. Builds a Wake-on-LAN
--- magic packet and saves it for later use with :worker(). Returns true if no errors were encountered, otherwise a nil.
function wol:configure (path)
	local fd = file.open(path)
	if not fd then
		print("Config file not found", path)
		return
	end
	local line = fd:readline()
	fd:close()
	fd = nil
	self.mac, self.addr = line:match("^(%S+)%s+(%S+)")
	self.data = ""
	for octet in self.mac:gmatch("%x%x") do
		self.data = self.data .. string.char(tonumber(octet, 16))
	end
	if #self.data ~= 6 then
		print(string.format("Invalid MAC\t%q", self.mac))
		return
	end
	self.data = string.char(0xff):rep(6) .. self.data:rep(16)
	return true
end


--- Initializes and returns worker that implements :sendout(interval, times, callback) that attempts to wake up
--- designated host number of [[times]] each separated by [[interval]]. After all attempts [[callback]] is called.
function wol:worker ()
	return {
		config = self,
		udp = net.createUDPSocket(),
		timer = tmr.create(),
		count = 0,
		sendout = function (self, interval, times, cb)
			self.times = times
			return self.timer:alarm(interval, tmr.ALARM_SEMI, function (timer)
				self.count = self.count + 1
				if self.count <= self.times then
					print("Waking up", self.config.mac, self.config.addr)
					self.udp:send(self.config.port, self.config.addr, self.config.data)
					timer:start()
				else
					timer:unregister()
					cb()
				end
			end)
		end,
	}
end


wol.timer:register(1000, tmr.ALARM_SINGLE, function ()
	gpio.mode(4, gpio.OUTPUT)
	gpio.write(4, gpio.HIGH)
	if not wol:configure("wakeup.conf") then
		error("Could not configure wakeup")
	end
	wifi.setmode(wifi.STATION, false)

	wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function ()
		local waker = wol:worker()
		gpio.write(4, gpio.LOW)
		waker:sendout(500, 5, function ()
			wifi.setmode(wifi.NULLMODE, false)
			gpio.write(4, gpio.HIGH)
		end)
	end)

	wifi.sta.connect()
end)


return function ()
	wol.timer:start()
end