写一个kindle同步插件(一)
前面说过动了把自己的生活数据汇总起来的想法,虽然最近挣扎于学Java和实习的事情,还是忍不住想要动手了。尤其是昨天上午看到Kindle已经完美越狱的消息(然而好几个月之前就可以了啊啊啊啊今天才发现),顿时感觉阅读数据有着落了,先把这部分做完。
方案选择
搜了一番同步Kindle数据的方法,主要有三种:
- 一种是利用Kindle的家长监护功能(parental control)。设置之后就可以记录本月阅读时间、页数,设置每天阅读目标之后还有完成目标数。这种方法最简单稳定,效果图(资料来自这里)是这样的:
- 另一种是越狱刷多看。多看统计的阅读记录还能与其他平台多看APP上的阅读记录合并,统计信息更为全面。
- 最后还搜到了一个kindle脚本,越狱之后从Kindle系统日志中读取阅读记录并呈现出来。效果图如下:
由于我的最终目的是采集Kindle阅读信息再进行汇总处理,所以前两种无法导出的方式自然就不适用了,主要思路也基于第三种方式进行改进。不过还是建议不想折腾的朋友试试前两种。
Step0 越狱Kindle
暑假刚买的时候听说Paperwhite3只能拆机飞线用串口越狱,懒得拆机加上作为阅读器还是以稳定为主所以一直没动手。昨天意外发现Paperwhite3、Voyage、Oasis都有了不拆机完美越狱(中文教程 & 英文教程),而且以后系统升级越狱状态依然保留(只是插件需要重新安装)。于是花了三四个小时越狱、升级系统到5.8.7、安装了一堆必需的插件(MrPI、KUAL、Helper、USBNetwork、KOReader)。话说KOReader重排版效果真是不错,就是不知道阅读记录会不会被包含。
秀一下越狱后界面O(∩_∩)O~~:
Step1 KUAL插件分析
下载了上面提到的Kindle统计脚本之后使用了一下,功能比较简单,但是在这个基础上修改也不会太难。然后就开始了艰难的修改之路(大雾)。
插件结构是这样的:
找了一下KUAL开发文档(吐槽一下mobilread论坛大神不少,但是文档还真是难找)之后大概看懂了插件结构,主要涉及下面几个文件:
./menu.json:
定义了菜单按钮和每个按钮绑定的执行脚本,比如向./bin/metric_setup.sh发送enable、disable、reset来执行启用、禁用和重置操作。 对应关系如下:
按钮 | 脚本 |
---|---|
查看阅读统计 | metric.sh |
禁用阅读统计 | metric_setup.sh |
清除统计记录 | metric_setup.sh |
./bin/metric.sh
计算累积阅读时间和今日阅读时间,每次点击“查看阅读统计”时执行一次。
具体做法是从$BASEDIR/log/metrics_generic_result读取阅读记录:每行代表一条记录,第一列记录写入时间,第二列阅读时长(毫秒),然后从/var/log/metrics_generic中读取记录保存到$BASEDIR/log/metrics_generic_temp(格式与上相同)并累加计算。
### ./bin/service.sh:
抽取系统日志中的阅读时长信息并保存到$BASEDIR/log/metrics_generic_result中。
系统日志中与阅读相关的信息保存在/var/log/metrics_generic中,一段时间后压缩到
/var/local/log/metrics_generic_%08d*中,需要注意的是,metrics_generic中的日志会被不断压缩并追加到/var/local/log/*下的对应文件,直到达到一定大小(未确认触发条件)再建立新的压缩文件。同时,旧的压缩日志会定期被系统删除(未确认触发条件),在/var/local/log/目录下有metrics_generic_oldest和metrics_generic_youngest两个文件记录了最老和最新压缩日志的编号(8位整数)。同时,此脚本在$BASEDIR/etc下建立metrics_generic_current文件记录下一个被处理的压缩日志编号。
### ./bin/metric_setup.sh:
执行对应的菜单操作。
从./menu.json中可以看出,此脚本接受三个参数:
1. enable: 开启阅读统计
在/etc/crontab/root中写入定时任务以每30分钟执行一次./bin/metric_service.h,同时在./etc/下创建enable文件。
2. disable: 禁用阅读统计
删除上述定时任务并删除enable文件
3. reset: 清除统计记录
删除./etc和./log下的所有文件
看这几个bash脚本才发现几乎把语法忘得差不多了,恶补了一番之后有因为手头没有Kindle原始日志文件(/var/local/log/metrics_generic_%08d*),对脚本的理解也模模糊糊,于是又去装了USBNetwork以便用ssh和filezilla直接对Kindle进行操作。昨天晚上出去吃饭今天上午打球好累,先写到这里吧。
to be continue…
2017.02.09更新:
Step2 开始动手!
最终目标很远,那么先完成一个小目标——添加一点功能同时熟悉一下环境好了。
添加月份、星期统计,
当前插件已经获取了时间信息,每行记录都包含两列数据:记录时间和阅读时长。那么只需要在累计的时候加入星期和月份判断的代码就行,话不多说直接上代码:
1 | # ./bin/metric.sh |
BUG-时间起始问题
最初插件中直接把metrics_generic_result中读取的时间作为本次记录开始时间,不过后来分析日志的时候发现,metrics_generic中的获取的第一列总是与写入时间相同,因此这个字段应当为本次阅读结束时间,所以添加了上述第14行代码:
1 | # ./bin/metric.sh |
BUG-莫名的时间归零?
之前在贴吧看到有人说有时候会出现今日统计变成0的情况,我今天上午也发现,用了一段时间之后总时间和今日阅读时间都莫名减少,一番纠结最终解决了这个问题︿( ̄︶ ̄)︿
前面讲到系统日志的rotate机制,当前日志保存在metrics_generic中,一段时间后压缩到/var/local/log/下,而插件在统计时间的时候也根据metrics_generic_youngest保证了压缩后的日志记录都加入到插件目录下的metrics_generic_result中,当前日志metrics_generic中的记录加入到metrics_generic_temp中,统计时两者都有计算,那么为什么会丢失数据呢?跟踪了日志变化之后发现,youngest对应的压缩日志文件并不是一成不变的,metrics_generic被移除后并没有直接新建一个压缩日志文件,而是追加到了youngest中(未超出限制的情况下)。这样的话,youngest对应的最新压缩日志被扫描过一次之后,由于current的值标记了当前文件已被处理,所以即使metrics_generic中的数据被追加到youngest对应文件中,这部分数据也不会添加进metrics_generic_result中,同时由于压缩后的数据已经metrics_generic中移除,所以也不会被加入metrics_generic_temp中,这部分信息消失了!
找到了原因,解决起来也就简单了:只要稍做调整,把youngest对应的压缩日志数据和metrcis_generic中的未压缩数据都加入到metrics_generic_temp中,并且前者在定时处理压缩日志时覆盖写入,后者在统计数据时追加写入,这样只要在统计数据之前执行一次定时任务,就可以保证所有日志信息都被计算\(^o^)/YES!
将metrics_generic记录追加到metrics_generic_temp:
1 | # ./bin/metric.sh |
将youngest对应记录覆盖到metrics_generic_temp:
1 | # ./bin/metric_service.sh |
信息展示
加入了一个项目信息显示的按钮,没啥好说的就不赘述了。
当前成果展示
总结一下的话,修复了原有的bug,加入了本月和本周累计,添加了一点项目说明。更多的功能敬请期待 ^_^
当前效果图: