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