summaryrefslogtreecommitdiff
path: root/wakeup.lua
diff options
context:
space:
mode:
Diffstat (limited to 'wakeup.lua')
-rw-r--r--wakeup.lua133
1 files changed, 82 insertions, 51 deletions
diff --git a/wakeup.lua b/wakeup.lua
index 8b9a893..ec8b78a 100644
--- a/wakeup.lua
+++ b/wakeup.lua
@@ -15,6 +15,21 @@ function magic_packet (mac)
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
+
+
--- Perform the most basic preparations right after device booted up.
function wakeup:boot ()
gpio.write(4, gpio.HIGH)
@@ -29,6 +44,18 @@ end
wakeup.step = wakeup.boot
+--- Will tick for N [[ticks]] and then switch into a state [[after]].
+local
+function start_timeout (ticks, after)
+ local self = new_counter(ticks)
+ return function (wakeup)
+ if not self:up() then
+ wakeup = after
+ end
+ end
+end
+
+
--- Marks a failure that is pointless to attempt to recover from, e.g., if provided configuration is incomplete.
function wakeup:hard_failure (timer)
print("Aborting...")
@@ -43,7 +70,7 @@ end
function wakeup:connect ()
- self.step = self.wait_for_ip
+ self.step = start_timeout(10, self.soft_failure)
wifi.eventmon.register(wifi.eventmon.STA_GOT_IP, function ()
self.step = self.sync_time
end)
@@ -52,21 +79,8 @@ function wakeup:connect ()
end
-function wakeup:wait_for_ip ()
- -- no-op -- TODO: soft_failure if too long?
-end
-
-
-function wakeup:now ()
- local time = rtctime.epoch2cal(rtctime.get())
- time.year = nil
- time.sec = nil
- return time
-end
-
-
function wakeup:sync_time ()
- self.step = self.wait_for_time
+ self.step = start_timeout(10, self.soft_failure)
sntp.sync(
self.sntp,
function ()
@@ -79,37 +93,6 @@ function wakeup:sync_time ()
end
-function wakeup:wait_for_time ()
- -- no-op -- TODO: soft_failure if too long?
-end
-
-
-local
-function compare (time, pattern)
- for key, value in pairs(pattern) do
- if time[key] ~= value then
- return false
- end
- end
- return true
-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
-
-
--- Creates new state machine action that sends out Wake-on-LAN magic packets to configured host N [[times]].
local
function start_sendout (times)
@@ -121,24 +104,72 @@ function start_sendout (times)
self.udp:send(wakeup.port, wakeup.addr, wakeup.data)
else
self.udp:close()
- timer:unregister()
- wifi.setmode(wifi.NULLMODE, false)
gpio.write(4, gpio.HIGH)
+ wifi.setmode(wifi.NULLMODE, false)
+ timer:interval(61000)
+ self.step = self.soft_failure
print("Done")
end
end
end
+--- Current UTC wall clock time.
+local
+function now ()
+ local time = rtctime.epoch2cal(rtctime.get())
+ return {hour = time.hour, min = time.min}
+end
+
+
+--- Time in minutes to next occurrence of [[pattern]] starting from [[time]].
+local
+function upcoming (pattern, time)
+ local hours = 0
+ if pattern.hour then
+ hours = pattern.hour - time.hour
+ if hours < 0 then
+ hours = hours + 24
+ end
+ end
+ local minutes = 0
+ if pattern.min then
+ minutes = pattern.min - time.min
+ if minutes < 0 then
+ minutes = minutes + 60
+ if hours > 0 then
+ hours = hours - 1
+ end
+ end
+ end
+ return hours * 60 + minutes
+end
+
+
function wakeup:check_time (timer)
- if compare(self:now(), self.when) then
+ local left = upcoming(self.when, now())
+ if left == 0 then
gpio.write(4, gpio.LOW)
self.step = start_sendout(5)
+ elseif left > 5 then
+ print(string.format("Need to wait total %d minutes", left))
+ left = left - 5
+ if left > 50 then
+ left = 50
+ end
+ self.left = left
+ self.step = start_timeout(3, self.sleep)
+ print(string.format("Going to sleep %d minutes", left))
else
- print("Not yet time")
- timer:unregister()
+ print(string.format("Wake-up in %d minutes", left))
+ timer:interval(15000)
end
end
+function wakeup:sleep ()
+ rtctime.dsleep(self.left * 6e7, 1)
+end
+
+
return wakeup