main.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. PROJECT = "EinkBook-LuatOS"
  2. VERSION = "1.0.0"
  3. MOD_TYPE = rtos.bsp()
  4. log.info("MOD_TYPE", MOD_TYPE)
  5. sys = require("sys")
  6. wifiLib = require("wifiLib")
  7. httpLib = require("httpLib")
  8. tag = "EINKBOOK"
  9. -- 是否启用配网功能(配合esptouch使用)
  10. USE_SMARTCONFIG = false
  11. -- 这是已有的电纸书服务端地址,如果自己搭建或下面这个服务失效了,请修改
  12. serverAdress = "http://47.96.229.157:2333/"
  13. -- 改为需要连接的WiFi名称和密码(使用2.4Ghz频段,ESP32C3无法使用5GHz WiFi)
  14. SSID, PASSWD = "Xiaomi_AX6000", "Air123456"
  15. waitHttpTask, waitDoubleClick = false, false
  16. einkPrintTime = 0
  17. PAGE, gpage = "LIST", 1
  18. onlineBooksTable, onlineBooksShowTable, onlineBooksShowTableTmp, einkBooksIndex, onlineBooksTableLen = {}, {}, {}, 1, 0
  19. gBTN, gPressTime, gShortCb, gLongCb, gDoubleCb, gBtnStatus = 0, 1000, nil, nil, nil, "IDLE"
  20. function printTable(tbl, lv)
  21. lv = lv and lv .. "\t" or ""
  22. print(lv .. "{")
  23. for k, v in pairs(tbl) do
  24. if type(k) == "string" then
  25. k = "\"" .. k .. "\""
  26. end
  27. if "string" == type(v) then
  28. local qv = string.match(string.format("%q", v), ".(.*).")
  29. v = qv == v and '"' .. v .. '"' or "'" .. v:toHex() .. "'"
  30. end
  31. if type(v) == "table" then
  32. print(lv .. "\t" .. tostring(k) .. " = ")
  33. printTable(v, lv)
  34. else
  35. print(lv .. "\t" .. tostring(k) .. " = " .. tostring(v) .. ",")
  36. end
  37. end
  38. print(lv .. "},")
  39. end
  40. function getTableSlice(intable, startIndex, endIndex)
  41. local outTable = {}
  42. for i = startIndex, endIndex do
  43. table.insert(outTable, intable[i])
  44. end
  45. return outTable
  46. end
  47. function getTableLen(t)
  48. local count = 0
  49. for _, _ in pairs(t) do
  50. count = count + 1
  51. end
  52. return count
  53. end
  54. function formatOnlineBooksTable(inTable)
  55. local outTable = {}
  56. local i = 1
  57. for k, v in pairs(inTable) do
  58. v["index"] = i
  59. table.insert(outTable, {
  60. [k] = v
  61. })
  62. i = i + 1
  63. end
  64. return outTable
  65. end
  66. function longTimerCb()
  67. gBtnStatus = "LONGPRESSED"
  68. gLongCb()
  69. end
  70. function btnHandle(val)
  71. if val == 0 then
  72. if waitDoubleClick == true then
  73. sys.timerStop(gShortCb)
  74. gDoubleCb()
  75. waitDoubleClick = false
  76. return
  77. end
  78. sys.timerStart(longTimerCb, gPressTime)
  79. gBtnStatus = "PRESSED"
  80. else
  81. sys.timerStop(longTimerCb)
  82. if gBtnStatus == "PRESSED" then
  83. sys.timerStart(gShortCb, 500)
  84. waitDoubleClick = true
  85. gBtnStatus = "IDLE"
  86. elseif gBtnStatus == "LONGPRESSED" then
  87. gBtnStatus = "IDLE"
  88. end
  89. end
  90. end
  91. function btnSetup(gpioNumber, pressTime, shortCb, longCb, doubleCb)
  92. gpio.setup(gpioNumber, btnHandle, gpio.PULLUP)
  93. gPressTime = pressTime
  94. gShortCb = shortCb
  95. gLongCb = longCb
  96. gDoubleCb = doubleCb
  97. end
  98. function showBookList(index)
  99. local firstIndex
  100. for k, v in pairs(onlineBooksShowTableTmp[1]) do
  101. firstIndex = v["index"]
  102. end
  103. if index > firstIndex + 10 then
  104. onlineBooksShowTableTmp = getTableSlice(onlineBooksShowTable, index - 10, index)
  105. end
  106. if index < firstIndex then
  107. onlineBooksShowTableTmp = getTableSlice(onlineBooksShowTable, index, index + 10)
  108. end
  109. einkShowStr(0, 16, "图书列表", 0, true)
  110. local ifShow = false
  111. local len = getTableLen(onlineBooksTable)
  112. local showLen = getTableLen(onlineBooksShowTableTmp)
  113. if len == 0 then
  114. einkShowStr(0, 32, "暂无在线图书", 0, false, true)
  115. return
  116. end
  117. local i = 1
  118. for k, v in pairs(onlineBooksShowTableTmp) do
  119. for name, info in pairs(v) do
  120. local bookName = string.split(name, ".")[1]
  121. local bookSize = tonumber(info["size"]) / 1024 / 1024
  122. if i == showLen then
  123. ifShow = true
  124. end
  125. if info["index"] == index then
  126. eink.rect(0, 16 * i, 200, 16 * (i + 1), 0, 1, nil, ifShow)
  127. einkShowStr(0, 16 * (i + 1), bookName .. " " .. string.format("%.2f", bookSize) .. "MB", 1, nil,
  128. ifShow)
  129. else
  130. einkShowStr(0, 16 * (i + 1), bookName .. " " .. string.format("%.2f", bookSize) .. "MB", 0, nil,
  131. ifShow)
  132. end
  133. i = i + 1
  134. end
  135. end
  136. end
  137. function showBook(bookName, bookUrl, page)
  138. sys.taskInit(function()
  139. waitHttpTask = true
  140. for i = 1, 3 do
  141. local result, code, data = httpLib.request("GET", bookUrl .. "/" .. page)
  142. log.info("SHOWBOOK", result, code)
  143. if result == false or code == -1 or code == 0 then
  144. log.error("SHOWBOOK", "获取图书内容失败 ", data)
  145. else
  146. local bookLines = json.decode(data)
  147. for k, v in pairs(bookLines) do
  148. if k == 1 then
  149. einkShowStr(0, 16 * k, v, 0, true, false)
  150. elseif k == #bookLines then
  151. einkShowStr(0, 16 * k, v, 0, false, false)
  152. else
  153. einkShowStr(0, 16 * k, v, 0, false, false)
  154. end
  155. end
  156. einkShowStr(60, 16 * 12 + 2, page .. "/" .. onlineBooksTable[bookName]["pages"], 0, false, true)
  157. break
  158. end
  159. end
  160. waitHttpTask = false
  161. end)
  162. end
  163. function btnShortHandle()
  164. if waitHttpTask == true then
  165. waitDoubleClick = false
  166. return
  167. end
  168. if PAGE == "LIST" then
  169. if einkBooksIndex == onlineBooksTableLen then
  170. einkBooksIndex = 1
  171. else
  172. einkBooksIndex = einkBooksIndex + 1
  173. end
  174. showBookList(einkBooksIndex)
  175. else
  176. local i = 1
  177. local bookName = nil
  178. for k, v in pairs(onlineBooksTable) do
  179. if i == einkBooksIndex then
  180. bookName = k
  181. end
  182. i = i + 1
  183. end
  184. local thisBookPages = tonumber(onlineBooksTable[bookName]["pages"])
  185. if thisBookPages == gpage then
  186. waitDoubleClick = false
  187. return
  188. end
  189. gpage = gpage + 1
  190. showBook(bookName, serverAdress .. string.urlEncode(bookName), gpage)
  191. log.info(bookName, gpage)
  192. fdb.kv_set(bookName, gpage)
  193. end
  194. waitDoubleClick = false
  195. end
  196. function btnLongHandle()
  197. if waitHttpTask == true then
  198. return
  199. end
  200. if PAGE == "LIST" then
  201. PAGE = "BOOK"
  202. local i = 1
  203. local bookName = nil
  204. for k, v in pairs(onlineBooksTable) do
  205. if i == einkBooksIndex then
  206. bookName = k
  207. end
  208. i = i + 1
  209. end
  210. local pageCache = fdb.kv_get(bookName)
  211. log.info(bookName, pageCache)
  212. if pageCache == nil then
  213. gpage = 1
  214. showBook(bookName, serverAdress .. string.urlEncode(bookName), gpage)
  215. else
  216. gpage = pageCache
  217. showBook(bookName, serverAdress .. string.urlEncode(bookName), pageCache)
  218. end
  219. elseif PAGE == "BOOK" then
  220. PAGE = "LIST"
  221. showBookList(einkBooksIndex)
  222. end
  223. end
  224. function btnDoublehandle()
  225. if waitHttpTask == true then
  226. return
  227. end
  228. if PAGE == "LIST" then
  229. if einkBooksIndex == 1 then
  230. einkBooksIndex = onlineBooksTableLen
  231. else
  232. einkBooksIndex = einkBooksIndex - 1
  233. end
  234. showBookList(einkBooksIndex)
  235. else
  236. if gpage == 1 then
  237. return
  238. end
  239. gpage = gpage - 1
  240. local i = 1
  241. local bookName = nil
  242. for k, v in pairs(onlineBooksTable) do
  243. if i == einkBooksIndex then
  244. bookName = k
  245. end
  246. i = i + 1
  247. end
  248. log.info(bookName, gpage)
  249. fdb.kv_set(bookName, gpage)
  250. showBook(bookName, serverAdress .. string.urlEncode(bookName), gpage)
  251. end
  252. end
  253. function einkShowStr(x, y, str, colored, clear, show)
  254. if einkPrintTime > 20 then
  255. einkPrintTime = 0
  256. eink.rect(0, 0, 200, 200, 0, 1)
  257. eink.show(0, 0, true)
  258. eink.rect(0, 0, 200, 200, 1, 1)
  259. eink.show(0, 0, true)
  260. end
  261. if clear == true then
  262. eink.clear()
  263. end
  264. eink.print(x, y, str, colored)
  265. if show == true then
  266. einkPrintTime = einkPrintTime + 1
  267. eink.show(0, 0, true)
  268. end
  269. end
  270. sys.taskInit(function()
  271. assert(fdb.kvdb_init("env", "onchip_flash") == true, tag .. ".kvdb_init ERROR")
  272. eink.model(eink.MODEL_1in54)
  273. if MOD_TYPE == "AIR101" then
  274. eink.setup(1, 0, 16, 19, 17, 20)
  275. elseif MOD_TYPE == "ESP32C3" then
  276. eink.setup(1, 2, 11, 10, 6, 7)
  277. end
  278. eink.setWin(200, 200, 0)
  279. eink.clear(0, true)
  280. eink.show(0, 0)
  281. eink.clear(1, true)
  282. eink.show(0, 0)
  283. eink.setFont(fonts.get("sarasa_regular_12"))
  284. if USE_SMARTCONFIG == true then
  285. einkShowStr(0, 16, "开机中 等待配网...", 0, false, true)
  286. local connectRes = wifiLib.connect()
  287. if connectRes == false then
  288. einkShowStr(0, 16, "配网失败 重启中...", 0, true, true)
  289. rtos.reboot()
  290. end
  291. else
  292. einkShowStr(0, 16, "开机中...", 0, false, true)
  293. local connectRes = wifiLib.connect(SSID, PASSWD)
  294. if connectRes == false then
  295. einkShowStr(0, 16, "联网失败 重启中...", 0, true, true)
  296. rtos.reboot()
  297. end
  298. end
  299. for i = 1, 5 do
  300. local result, code, data = httpLib.request("GET", serverAdress .. "getBooks")
  301. if result == false or code == -1 or code == 0 then
  302. log.error(tag, "获取图书列表失败 ", data)
  303. if i == 5 then
  304. einkShowStr(0, 16, "连接图书服务器失败 正在重启", 0, true, true)
  305. rtos.reboot()
  306. end
  307. else
  308. onlineBooksTable = json.decode(data)
  309. printTable(onlineBooksTable)
  310. onlineBooksTableLen = getTableLen(onlineBooksTable)
  311. onlineBooksShowTable = formatOnlineBooksTable(onlineBooksTable)
  312. onlineBooksShowTableTmp = getTableSlice(onlineBooksShowTable, 1, 11)
  313. showBookList(1)
  314. btnSetup(9, 1000, btnShortHandle, btnLongHandle, btnDoublehandle)
  315. break
  316. end
  317. sys.wait(1000)
  318. end
  319. end)
  320. sys.run()