local wakeup = { port = 9, } --- 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 wakeup: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 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 --- Sets up Wake Up to run when wifi is connected and configured in a network. Runs callbacks [[before]] send-outs, and --- [[after]] they are done. function wakeup:setup (before, after) if not self:configure("wakeup.conf") then error("Could not configure wakeup") end wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function () before() self:sendout(500, 5, after) end) end return function () gpio.write(4, gpio.HIGH) gpio.mode(4, gpio.OUTPUT) tmr.create():alarm(1000, tmr.ALARM_SINGLE, function () wakeup:setup( function () gpio.write(4, gpio.LOW) end, function () wifi.setmode(wifi.NULLMODE, false) gpio.write(4, gpio.HIGH) end ) wifi.setmode(wifi.STATION, false) wifi.sta.connect() end) end