Skip to content

[feat, Kobo] Autoshutdown#5335

Merged
Frenzie merged 21 commits intokoreader:masterfrom
Frenzie:autoshutdown
Sep 12, 2019
Merged

[feat, Kobo] Autoshutdown#5335
Frenzie merged 21 commits intokoreader:masterfrom
Frenzie:autoshutdown

Conversation

@Frenzie
Copy link
Copy Markdown
Member

@Frenzie Frenzie commented Sep 7, 2019

The methods used here will likely work on most embedded devices, which is why I put them in UIManagerin their own module, separate from Kobo.

See https://www.mobileread.com/forums/showthread.php?p=3886403#post3886403 for more context.

Fixes #3806.

@Frenzie Frenzie added this to the 2019.10 milestone Sep 7, 2019
dbg:guard(UIManager, 'unschedule',
function(self, action) assert(action ~= nil) end)

--- @todo Stick this in base/ffi and reference here?
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, too much C/FFI here :) when there is none already.

Haven't checked much the autosuspend plugin, that I have disabled (so, I won't benefit from autoshutdown, which is fine for me). Haven't checked much of the ffi/rtc stuff either, but reading the other links, I trust you got that right :)

Is that uimanager alarm management abstracted enough from its shutdown use so it can eventually be used for other features (like update rss/news, autoupdate koreader,...)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, too much C/FFI here :) when there is none already.

Much easier to prototype. ;-) Actually this is the abstracted version of the proof of concept done purely in kobo/device. For the moment I've still got a branch with that here. Perhaps I should add a diff here for posterity. ^_^

Is that uimanager alarm management abstracted enough from its shutdown use so it can eventually be used for other features (like update rss/news, autoupdate koreader,...)?

Sure, it's (purposefully) completely agnostic as to what's done with the wakeup. I'll update it with a wakeup_action or some such later to finalize that.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I should add that unless someone writes a wakeup scheduler that manages things, this implementation is one wakeup action only. So that would be either update Wallabag/whatever or autoshutdown. But that's basically unrelated to the methods for scheduling the wakeup.

To clarify, you can only schedule one wakeup. So if you wake up to sync, then afterward you have to schedule either the next sync or the autoshutdown depending on which would come first. I suppose the scheduler could be as simple as a table of upcoming actions in proper order, holding a reference to the scheduled action.

I have no interest in implementing such a thing right now, and I think I'd rather keep it for a follow-up PR even if I do it later.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Diff for the part of the v1 prototype that didn't carry over into this PR:

diff --git a/frontend/device/kobo/device.lua b/frontend/device/kobo/device.lua
index 35edf5d3..6a124352 100644
--- a/frontend/device/kobo/device.lua
+++ b/frontend/device/kobo/device.lua
@@ -534,7 +534,13 @@ local function getProductId()
 end
 
 local unexpected_wakeup_count = 0
+local wakeup_scheduled = false
 local function check_unexpected_wakeup()
+    if wakeup_scheduled then
+        logger.dbg("Kobo suspend: scheduled wakeup for shutdown")
+        local UIManager = require("ui/uimanager")
+        UIManager:poweroff_action()
+    end
     logger.dbg("Kobo suspend: checking unexpected wakeup:",
                unexpected_wakeup_count)
     if unexpected_wakeup_count == 0 or unexpected_wakeup_count > 20 then
@@ -553,7 +559,49 @@ end
 
 function Kobo:getUnexpectedWakeup() return unexpected_wakeup_count end
 
+local ffi = require("ffi")
+local C = ffi.C
+-- for ioctl header definition:
+local dummy = require("ffi/posix_h")
+local rtc = require("ffi/rtc_h")
+
 function Kobo:suspend()
+    local t = ffi.new("time_t[1]")
+    t[0] = C.time(NULL)
+    t[0] = t[0] + 12
+    print(t[0])
+
+    local ptm = ffi.new("struct tm")
+    ptm = C.gmtime(t)
+    print(ptm.tm_sec)
+
+    local wake = ffi.new("struct rtc_wkalrm")
+    wake.time.tm_sec = ptm.tm_sec
+    wake.time.tm_min = ptm.tm_min
+    wake.time.tm_hour = ptm.tm_hour
+    wake.time.tm_mday = ptm.tm_mday
+    wake.time.tm_mon = ptm.tm_mon
+    wake.time.tm_year = ptm.tm_year
+    -- wday, yday, and isdst fields are unused by Linux
+    wake.time.tm_wday = -1;
+    wake.time.tm_yday = -1;
+    wake.time.tm_isdst = -1;
+    print(wake.time.tm_sec)
+
+    wake.enabled = 1
+    --wake.time = rtc_time
+
+    local rtc0 = C.open("/dev/rtc0", C.O_RDONLY)
+    print(rtc0, ffi.string(C.strerror(ffi.errno())))
+    local err = C.ioctl(rtc0, C.RTC_WKALM_SET, wake)
+    print(err, ffi.string(C.strerror(ffi.errno())))
+    local err2 = C.close(rtc0)
+    print(err2, ffi.string(C.strerror(ffi.errno())))
+
+    if err == 0 then
+        wakeup_scheduled = true
+    end
+
     logger.info("Kobo suspend: going to sleep . . .")
     local UIManager = require("ui/uimanager")
     UIManager:unschedule(check_unexpected_wakeup)

@Frenzie
Copy link
Copy Markdown
Member Author

Frenzie commented Sep 7, 2019

Btw @NiLuJe if you woudn't mind could you add these to base the right way? :-)

time_t mktime(struct tm *tm);
double difftime(time_t time1, time_t time0);

NiLuJe added a commit to NiLuJe/koreader-base that referenced this pull request Sep 7, 2019
@NiLuJe
Copy link
Copy Markdown
Member

NiLuJe commented Sep 7, 2019

Btw @NiLuJe if you woudn't mind could you add these to base the right way? :-)

time_t mktime(struct tm *tm);
double difftime(time_t time1, time_t time0);

Done! :)

Sidebar: difftime is possibly overkill on Linux (time_t is an int64_t) ;).

Frenzie pushed a commit to koreader/koreader-base that referenced this pull request Sep 7, 2019
@Frenzie Frenzie changed the title [feat, Kobo] Autoshutdown WIP [feat, Kobo] Autoshutdown Sep 7, 2019
@Frenzie
Copy link
Copy Markdown
Member Author

Frenzie commented Sep 8, 2019

What's this pipefail nonsense on CircleCI all of a sudden?

@Frenzie Frenzie changed the title WIP [feat, Kobo] Autoshutdown [feat, Kobo] Autoshutdown Sep 8, 2019
Frenzie added a commit to Frenzie/koreader-base that referenced this pull request Sep 8, 2019
This will allow for scheduling wakeups.

Prerequisite for <koreader/koreader#5335>.
Frenzie added a commit to Frenzie/koreader-base that referenced this pull request Sep 8, 2019
This will allow for scheduling wakeups.

Prerequisite for <koreader/koreader#5335>.
Frenzie added a commit to koreader/koreader-base that referenced this pull request Sep 9, 2019
This will allow for scheduling wakeups.

Prerequisite for <koreader/koreader#5335>.

Builds on <#967> and <#968>.
G_reader_settings:saveSetting("auto_suspend_timeout_seconds", autosuspend_timeout_seconds)
UIManager:show(InfoMessage:new{
text = _("This will take effect on next restart."),
text = T(_("The system will automatically suspend after %1 minutes of inactivity."),
Copy link
Copy Markdown
Member Author

@Frenzie Frenzie Sep 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe some logic to point out suspend/shutdown will occur first? Only devices with Device.wakeup_mgr (or some equivalent check) will be able to shutdown after suspend.

Copy link
Copy Markdown
Contributor

@poire-z poire-z left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't comment much about the autosuspend plugin, but the rest is fine.
(I have a thing with this plugin, and I don't want to dig into it anymore :) I did when it was created, to try to move into it some additional personal stuff that I had added when that was done in UIManager, to no avail... :)


local epoch = RTC:secondsFromNowToEpoch(seconds_from_now)

local old_upcoming_task = (self._task_queue[1] or {}).epoch
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially stumble on that, "task" being assigned an timestamp, while intuitively, a task is a callback.
So, may be just a comment saying "a task here is a combo of (epoch timestamp, callback).

Nothing more to add about WakeupMrg, looks quite fine and explicite.

@Frenzie
Copy link
Copy Markdown
Member Author

Frenzie commented Sep 9, 2019

The missing job output issue should be fixed: https://status.circleci.com/incidents/qfhr81gjzkb0

@poire-z AutoSuspend should actually be significantly easier to follow now.

Copy link
Copy Markdown
Contributor

@poire-z poire-z left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I still don't like this module :) but ok, had a quick look, feel free to discard my remarks, moreover if they are about code from before you started tweaking it.)

name = "autosuspend",
is_doc_only = false,
autoshutdown_sec = G_reader_settings:readSetting("autoshutdown_timeout_seconds") or default_autoshutdown_timeout_seconds,
settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/koboautosuspend.lua"),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You save into G_reader_settings. Is there still some reason to read this koboautosuspend.lua and loop thru candidates below? (alt: should you not save them into that plugin setting file, and forger about G_reader_settings here?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that you mention it, one of them is probably intended to be legacy. Given that the plugin-specific settings seem to stem from a migration out of the UIManager core, I'm guessing G_reader_settings is the one that should be deprecated.

end
end

function AutoSuspend:_deprecateLastTask()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good riddance:)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was convoluted and hard to follow. The changed method Just Works™ (thanks to the scheduleIn/unschedule methods I wrote in 2014 I might add with some pride).

function AutoSuspend:_deprecateLastTask()
self.settings_id = self.settings_id + 1
logger.dbg("AutoSuspend: deprecateLastTask ", self.settings_id)
function AutoSuspend:_unschedule()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now you're talking koreaderish.

-- when suspending and restart it after resume.
self:_unschedule()
if self:_enabledShutdown() and Device.wakeup_mgr then
Device.wakeup_mgr:addTask(self.autoshutdown_sec, UIManager.poweroff_action)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No pb with that, but autoshutdown delay applies after autosuspend delay, so it's actually autosuspend_set + autoshutdown_sec ?
Does all that work when suspend is disabled, and only shutdown enabled?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scheduling part above is only for suspending/shutting down while the device is active. On suspend that's all unscheduled (see two lines above), while the WakeupMgr takes care of scheduling the wakeup and executing the scheduled task.


function AutoSuspend:_start()
if self:_enabled() then
if self:_enabled() or self:_enabledShutdown() then
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@poire-z This is the answer to your question below in https://github.com/koreader/koreader/pull/5335/files#r322896802

@Frenzie Frenzie merged commit e257c4e into koreader:master Sep 12, 2019
@Frenzie Frenzie deleted the autoshutdown branch September 12, 2019 12:15
mwoz123 pushed a commit to mwoz123/koreader that referenced this pull request Mar 29, 2020
The methods used here will likely work on most embedded devices, which is why I put them in their own WakeupMgr interface/scheduler module, separate from Kobo.

See https://www.mobileread.com/forums/showthread.php?p=3886403#post3886403 for more context.

Fixes koreader#3806.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Automatic Power Off

3 participants