From 6e430351816299521461739ce40af0493e358d8a Mon Sep 17 00:00:00 2001 From: Aki Date: Sat, 13 Jan 2024 02:53:38 +0100 Subject: Implemented enough to wake up a sleepy server by connecting nodemcu to dc power --- run.lua | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 run.lua (limited to 'run.lua') diff --git a/run.lua b/run.lua new file mode 100644 index 0000000..3c22c30 --- /dev/null +++ b/run.lua @@ -0,0 +1,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 -- cgit v1.1