summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--+wakeup.example.lua22
-rw-r--r--.gitignore2
-rw-r--r--init.lua2
-rw-r--r--run.lua105
-rw-r--r--wakeup.lua86
5 files changed, 113 insertions, 104 deletions
diff --git a/+wakeup.example.lua b/+wakeup.example.lua
new file mode 100644
index 0000000..e65c8a6
--- /dev/null
+++ b/+wakeup.example.lua
@@ -0,0 +1,22 @@
+--- Fill this file and save it on the device as "+wakeup.lua".
+return {
+ --- MAC address of the device to wake up. Formatted as twelve hexadecimal characters separated or not, for example:
+ ---
+ --- "1a:2b:3c:4d:5e:6f"
+ --- "1a 2b 3c 4d 5e 6f"
+ --- "1a2b3c4d5e6f"
+ ---
+ --- These three are equivalent.
+ mac=nil,
+ --- Broadcast address to send the magic packet to.
+ addr="255.255.255.255",
+ --- Wake-on-LAN port.
+ port=9,
+ --- Not yet implemented time description of when to wake up the device.
+ when=nil,
+ --- Wi-Fi configuration same as passed to wifi.config(). It won't be used if left as nil. In this case user is
+ --- expected to manually configure and persist AP in the flash.
+ wifi=nil,
+ --- SNTP server address or table of addresses. See sntp.sync().
+ sntp="time.google.com",
+}
diff --git a/.gitignore b/.gitignore
index 7d12491..ae1c106 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-*.conf
++wakeup.lua
.venv/
diff --git a/init.lua b/init.lua
index 1756628..4727838 100644
--- a/init.lua
+++ b/init.lua
@@ -4,7 +4,7 @@ function init ()
wifi.setmode(wifi.NULLMODE, false)
local l, r = pcall(require, "run")
if not l then
- print("run.lua not found")
+ print("Could not load run.lua:", r)
return
end
RUN = r
diff --git a/run.lua b/run.lua
index 67e3fdf..43f7cad 100644
--- a/run.lua
+++ b/run.lua
@@ -1,105 +1,6 @@
-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
-
+local wakeup = require("wakeup")
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)
+ wakeup:init()
+ tmr.create():alarm(1000, tmr.ALARM_SINGLE, function () wakeup:run() end)
end
diff --git a/wakeup.lua b/wakeup.lua
new file mode 100644
index 0000000..9239fe1
--- /dev/null
+++ b/wakeup.lua
@@ -0,0 +1,86 @@
+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: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 ()
+ gpio.write(4, gpio.LOW)
+
+ self:sendout(500, 5, function ()
+ wifi.setmode(wifi.NULLMODE, false)
+ gpio.write(4, gpio.HIGH)
+ end)
+ end)
+end
+
+
+function wakeup:run ()
+ wifi.setmode(wifi.STATION, false)
+ wifi.sta.connect()
+end
+
+
+return wakeup