diff options
author | Aki <please@ignore.pl> | 2024-01-22 21:35:45 +0100 |
---|---|---|
committer | Aki <please@ignore.pl> | 2024-01-22 21:35:45 +0100 |
commit | 0ff40d99e0d9db70311a78011ad52e603beec0ab (patch) | |
tree | 657caa3fc2b7514e8a3473ca2dfde19ac684f5c8 | |
parent | 7b6c20b5c58014861e218e62cf0749bdd0ba727e (diff) | |
download | nodemcu-wakeup-0ff40d99e0d9db70311a78011ad52e603beec0ab.zip nodemcu-wakeup-0ff40d99e0d9db70311a78011ad52e603beec0ab.tar.gz nodemcu-wakeup-0ff40d99e0d9db70311a78011ad52e603beec0ab.tar.bz2 |
Implemented deep sleep that does not work currently
Doesn't seem to react to rstime.dsleep with RST connected to GPIO16
-rw-r--r-- | +wakeup.example.lua | 5 | ||||
-rw-r--r-- | wakeup.lua | 133 |
2 files changed, 85 insertions, 53 deletions
diff --git a/+wakeup.example.lua b/+wakeup.example.lua index 8672fc6..a60e684 100644 --- a/+wakeup.example.lua +++ b/+wakeup.example.lua @@ -12,11 +12,12 @@ return { addr="255.255.255.255", --- Wake-on-LAN port. port=9, - --- Not yet implemented time description of when to wake up the device. Currently: + --- On what hour and/or minutes to wahe up the device: --- --- {hour=23, min=0} + --- {min=30} --- - --- Will send wakeup packets each day on 23:00 UTC. + --- First will send wakeup packets each day on 23:00 UTC. Second will send them every half past each hour. 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. @@ -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 |