tiro-notes 0.51.61 → 0.51.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/package.json +1 -1
  2. package/node-build/cli.js +0 -309
  3. package/node-build/package.json +0 -28
  4. package/node-build/v6 copy.ino +0 -956
  5. package/node-build/v6.ino +0 -872
  6. /package/{node-build/README.md → README.md} +0 -0
  7. /package/{node-build/client → client}/appicons/icons/mac/icon.icns +0 -0
  8. /package/{node-build/client → client}/appicons/icons/png/1024x1024.png +0 -0
  9. /package/{node-build/client → client}/appicons/icons/png/128x128.png +0 -0
  10. /package/{node-build/client → client}/appicons/icons/png/16x16.png +0 -0
  11. /package/{node-build/client → client}/appicons/icons/png/24x24.png +0 -0
  12. /package/{node-build/client → client}/appicons/icons/png/256x256.png +0 -0
  13. /package/{node-build/client → client}/appicons/icons/png/32x32.png +0 -0
  14. /package/{node-build/client → client}/appicons/icons/png/48x48.png +0 -0
  15. /package/{node-build/client → client}/appicons/icons/png/512x512.png +0 -0
  16. /package/{node-build/client → client}/appicons/icons/png/64x64.png +0 -0
  17. /package/{node-build/client → client}/appicons/icons/win/icon.ico +0 -0
  18. /package/{node-build/client → client}/appicons/tiro_icon.icns +0 -0
  19. /package/{node-build/client → client}/appicons/tiro_icon.ico +0 -0
  20. /package/{node-build/client → client}/appicons/tiro_icon.png +0 -0
  21. /package/{node-build/client → client}/asset-manifest.json +0 -0
  22. /package/{node-build/client → client}/custom_icons/bottom-left.png +0 -0
  23. /package/{node-build/client → client}/custom_icons/bottom-right.png +0 -0
  24. /package/{node-build/client → client}/custom_icons/bottom.png +0 -0
  25. /package/{node-build/client → client}/custom_icons/check.svg +0 -0
  26. /package/{node-build/client → client}/custom_icons/left.png +0 -0
  27. /package/{node-build/client → client}/custom_icons/line.svg +0 -0
  28. /package/{node-build/client → client}/custom_icons/right.png +0 -0
  29. /package/{node-build/client → client}/custom_icons/top-left.png +0 -0
  30. /package/{node-build/client → client}/custom_icons/top-right.png +0 -0
  31. /package/{node-build/client → client}/custom_icons/top.png +0 -0
  32. /package/{node-build/client → client}/custom_icons/uncheck.svg +0 -0
  33. /package/{node-build/client → client}/custom_icons/view-1.svg +0 -0
  34. /package/{node-build/client → client}/custom_icons/view-2.svg +0 -0
  35. /package/{node-build/client → client}/custom_icons/view-3.svg +0 -0
  36. /package/{node-build/client → client}/custom_icons/view-4.svg +0 -0
  37. /package/{node-build/client → client}/favicon.png +0 -0
  38. /package/{node-build/client → client}/icon-192x192.png +0 -0
  39. /package/{node-build/client → client}/icon-256x256.png +0 -0
  40. /package/{node-build/client → client}/icon-384x384.png +0 -0
  41. /package/{node-build/client → client}/icon-512x512.png +0 -0
  42. /package/{node-build/client → client}/index.html +0 -0
  43. /package/{node-build/client → client}/manifest.json +0 -0
  44. /package/{node-build/client → client}/manifest.webmanifest +0 -0
  45. /package/{node-build/client → client}/service-worker.js +0 -0
  46. /package/{node-build/client → client}/static/css/12.394917b1.chunk.css +0 -0
  47. /package/{node-build/client → client}/static/js/0.b890b1cb.chunk.js +0 -0
  48. /package/{node-build/client → client}/static/js/1.24c0d2eb.chunk.js +0 -0
  49. /package/{node-build/client → client}/static/js/100.4020f20c.chunk.js +0 -0
  50. /package/{node-build/client → client}/static/js/101.21c27e18.chunk.js +0 -0
  51. /package/{node-build/client → client}/static/js/102.e3f94c8e.chunk.js +0 -0
  52. /package/{node-build/client → client}/static/js/103.18e92661.chunk.js +0 -0
  53. /package/{node-build/client → client}/static/js/104.cd956379.chunk.js +0 -0
  54. /package/{node-build/client → client}/static/js/105.1e2e5889.chunk.js +0 -0
  55. /package/{node-build/client → client}/static/js/106.5c24ba4b.chunk.js +0 -0
  56. /package/{node-build/client → client}/static/js/107.80b988bf.chunk.js +0 -0
  57. /package/{node-build/client → client}/static/js/108.fff04134.chunk.js +0 -0
  58. /package/{node-build/client → client}/static/js/109.ec78f8d9.chunk.js +0 -0
  59. /package/{node-build/client → client}/static/js/110.44788eb1.chunk.js +0 -0
  60. /package/{node-build/client → client}/static/js/12.6d6dc9bb.chunk.js +0 -0
  61. /package/{node-build/client → client}/static/js/12.6d6dc9bb.chunk.js.LICENSE.txt +0 -0
  62. /package/{node-build/client → client}/static/js/13.9e34d8ba.chunk.js +0 -0
  63. /package/{node-build/client → client}/static/js/14.a886302f.chunk.js +0 -0
  64. /package/{node-build/client → client}/static/js/15.01bf8225.chunk.js +0 -0
  65. /package/{node-build/client → client}/static/js/16.67051f41.chunk.js +0 -0
  66. /package/{node-build/client → client}/static/js/17.82cdd47c.chunk.js +0 -0
  67. /package/{node-build/client → client}/static/js/18.ddb404ef.chunk.js +0 -0
  68. /package/{node-build/client → client}/static/js/19.7dd55448.chunk.js +0 -0
  69. /package/{node-build/client → client}/static/js/2.b4b18203.chunk.js +0 -0
  70. /package/{node-build/client → client}/static/js/20.59f5165d.chunk.js +0 -0
  71. /package/{node-build/client → client}/static/js/21.79c4b0e8.chunk.js +0 -0
  72. /package/{node-build/client → client}/static/js/22.007e32b0.chunk.js +0 -0
  73. /package/{node-build/client → client}/static/js/23.f61a9d2c.chunk.js +0 -0
  74. /package/{node-build/client → client}/static/js/24.e0d7947e.chunk.js +0 -0
  75. /package/{node-build/client → client}/static/js/25.e8450ff4.chunk.js +0 -0
  76. /package/{node-build/client → client}/static/js/26.ea917da6.chunk.js +0 -0
  77. /package/{node-build/client → client}/static/js/27.40c86fd7.chunk.js +0 -0
  78. /package/{node-build/client → client}/static/js/28.36540711.chunk.js +0 -0
  79. /package/{node-build/client → client}/static/js/29.90bee6cc.chunk.js +0 -0
  80. /package/{node-build/client → client}/static/js/3.303b3d58.chunk.js +0 -0
  81. /package/{node-build/client → client}/static/js/30.41fd826a.chunk.js +0 -0
  82. /package/{node-build/client → client}/static/js/31.ceec3129.chunk.js +0 -0
  83. /package/{node-build/client → client}/static/js/32.f164128c.chunk.js +0 -0
  84. /package/{node-build/client → client}/static/js/33.0aa32cf1.chunk.js +0 -0
  85. /package/{node-build/client → client}/static/js/34.a7b2b96c.chunk.js +0 -0
  86. /package/{node-build/client → client}/static/js/35.d6fc00c0.chunk.js +0 -0
  87. /package/{node-build/client → client}/static/js/36.2c384957.chunk.js +0 -0
  88. /package/{node-build/client → client}/static/js/37.a4733489.chunk.js +0 -0
  89. /package/{node-build/client → client}/static/js/38.151ab2a6.chunk.js +0 -0
  90. /package/{node-build/client → client}/static/js/39.79ebafd7.chunk.js +0 -0
  91. /package/{node-build/client → client}/static/js/4.5e26b40b.chunk.js +0 -0
  92. /package/{node-build/client → client}/static/js/40.f3d995a0.chunk.js +0 -0
  93. /package/{node-build/client → client}/static/js/41.e90a9137.chunk.js +0 -0
  94. /package/{node-build/client → client}/static/js/42.bd656ca1.chunk.js +0 -0
  95. /package/{node-build/client → client}/static/js/43.8074805b.chunk.js +0 -0
  96. /package/{node-build/client → client}/static/js/44.8da981a2.chunk.js +0 -0
  97. /package/{node-build/client → client}/static/js/45.1a2b3b01.chunk.js +0 -0
  98. /package/{node-build/client → client}/static/js/46.2e55aca9.chunk.js +0 -0
  99. /package/{node-build/client → client}/static/js/47.57672172.chunk.js +0 -0
  100. /package/{node-build/client → client}/static/js/48.3bfd34d7.chunk.js +0 -0
  101. /package/{node-build/client → client}/static/js/49.c657ccf4.chunk.js +0 -0
  102. /package/{node-build/client → client}/static/js/5.f7811373.chunk.js +0 -0
  103. /package/{node-build/client → client}/static/js/50.36421e1d.chunk.js +0 -0
  104. /package/{node-build/client → client}/static/js/51.cd3bd891.chunk.js +0 -0
  105. /package/{node-build/client → client}/static/js/52.ddd90678.chunk.js +0 -0
  106. /package/{node-build/client → client}/static/js/53.8933ff1d.chunk.js +0 -0
  107. /package/{node-build/client → client}/static/js/54.1d25d19c.chunk.js +0 -0
  108. /package/{node-build/client → client}/static/js/55.f0195607.chunk.js +0 -0
  109. /package/{node-build/client → client}/static/js/56.931338e0.chunk.js +0 -0
  110. /package/{node-build/client → client}/static/js/57.8304da63.chunk.js +0 -0
  111. /package/{node-build/client → client}/static/js/58.3dbe9d9e.chunk.js +0 -0
  112. /package/{node-build/client → client}/static/js/59.d8dd3c13.chunk.js +0 -0
  113. /package/{node-build/client → client}/static/js/6.b8cf2c81.chunk.js +0 -0
  114. /package/{node-build/client → client}/static/js/60.e8ba53a7.chunk.js +0 -0
  115. /package/{node-build/client → client}/static/js/61.41f7057e.chunk.js +0 -0
  116. /package/{node-build/client → client}/static/js/62.8312dcd3.chunk.js +0 -0
  117. /package/{node-build/client → client}/static/js/63.ceff6f5a.chunk.js +0 -0
  118. /package/{node-build/client → client}/static/js/64.2b51a3a2.chunk.js +0 -0
  119. /package/{node-build/client → client}/static/js/65.5b662f09.chunk.js +0 -0
  120. /package/{node-build/client → client}/static/js/66.aed0e545.chunk.js +0 -0
  121. /package/{node-build/client → client}/static/js/67.c68e472b.chunk.js +0 -0
  122. /package/{node-build/client → client}/static/js/68.482d5776.chunk.js +0 -0
  123. /package/{node-build/client → client}/static/js/69.adf6efab.chunk.js +0 -0
  124. /package/{node-build/client → client}/static/js/7.5575eef7.chunk.js +0 -0
  125. /package/{node-build/client → client}/static/js/70.54d4c087.chunk.js +0 -0
  126. /package/{node-build/client → client}/static/js/71.e02a4ef4.chunk.js +0 -0
  127. /package/{node-build/client → client}/static/js/72.cdabbbd2.chunk.js +0 -0
  128. /package/{node-build/client → client}/static/js/73.b58eb627.chunk.js +0 -0
  129. /package/{node-build/client → client}/static/js/74.a7b0defd.chunk.js +0 -0
  130. /package/{node-build/client → client}/static/js/75.7ee75f2a.chunk.js +0 -0
  131. /package/{node-build/client → client}/static/js/76.88cf92c8.chunk.js +0 -0
  132. /package/{node-build/client → client}/static/js/77.64a32f3b.chunk.js +0 -0
  133. /package/{node-build/client → client}/static/js/78.e19d46e1.chunk.js +0 -0
  134. /package/{node-build/client → client}/static/js/79.2daf87c6.chunk.js +0 -0
  135. /package/{node-build/client → client}/static/js/8.977d1a5d.chunk.js +0 -0
  136. /package/{node-build/client → client}/static/js/80.2591cada.chunk.js +0 -0
  137. /package/{node-build/client → client}/static/js/81.4a8cdda6.chunk.js +0 -0
  138. /package/{node-build/client → client}/static/js/82.285db5b4.chunk.js +0 -0
  139. /package/{node-build/client → client}/static/js/83.c3ae3b75.chunk.js +0 -0
  140. /package/{node-build/client → client}/static/js/84.0316e16e.chunk.js +0 -0
  141. /package/{node-build/client → client}/static/js/85.da21c20c.chunk.js +0 -0
  142. /package/{node-build/client → client}/static/js/86.54af0d45.chunk.js +0 -0
  143. /package/{node-build/client → client}/static/js/87.c3e1d4bb.chunk.js +0 -0
  144. /package/{node-build/client → client}/static/js/88.6f1f304d.chunk.js +0 -0
  145. /package/{node-build/client → client}/static/js/89.9bf1904b.chunk.js +0 -0
  146. /package/{node-build/client → client}/static/js/9.3b7d0e8d.chunk.js +0 -0
  147. /package/{node-build/client → client}/static/js/90.f4f97bc7.chunk.js +0 -0
  148. /package/{node-build/client → client}/static/js/91.06e2ef0f.chunk.js +0 -0
  149. /package/{node-build/client → client}/static/js/92.05d93a9c.chunk.js +0 -0
  150. /package/{node-build/client → client}/static/js/93.84099dca.chunk.js +0 -0
  151. /package/{node-build/client → client}/static/js/94.c20443c3.chunk.js +0 -0
  152. /package/{node-build/client → client}/static/js/95.eef2f092.chunk.js +0 -0
  153. /package/{node-build/client → client}/static/js/96.1f09d3f2.chunk.js +0 -0
  154. /package/{node-build/client → client}/static/js/97.e7cce996.chunk.js +0 -0
  155. /package/{node-build/client → client}/static/js/98.ed47f20f.chunk.js +0 -0
  156. /package/{node-build/client → client}/static/js/99.038f33b0.chunk.js +0 -0
  157. /package/{node-build/client → client}/static/js/main.608d7586.chunk.js +0 -0
  158. /package/{node-build/client → client}/static/js/runtime-main.bbeed8c8.js +0 -0
  159. /package/{node-build/client → client}/static/media/book-solid.87f5b737.svg +0 -0
  160. /package/{node-build/client → client}/static/media/compact-disc-solid.55b6e50c.svg +0 -0
  161. /package/{node-build/client → client}/static/media/deco-bg-map.7ca9103b.png +0 -0
  162. /package/{node-build/client → client}/static/media/fa-brands-400.150de8ea.ttf +0 -0
  163. /package/{node-build/client → client}/static/media/fa-brands-400.e033a13e.woff2 +0 -0
  164. /package/{node-build/client → client}/static/media/fa-regular-400.3223dc79.woff2 +0 -0
  165. /package/{node-build/client → client}/static/media/fa-regular-400.d8747423.ttf +0 -0
  166. /package/{node-build/client → client}/static/media/fa-solid-900.4a2cd718.ttf +0 -0
  167. /package/{node-build/client → client}/static/media/fa-solid-900.bb975c96.woff2 +0 -0
  168. /package/{node-build/client → client}/static/media/fa-v4compatibility.0e3a648b.ttf +0 -0
  169. /package/{node-build/client → client}/static/media/fa-v4compatibility.68577e40.woff2 +0 -0
  170. /package/{node-build/client → client}/static/media/file-audio-solid.a76f99f0.svg +0 -0
  171. /package/{node-build/client → client}/static/media/file-code-solid.62b467ac.svg +0 -0
  172. /package/{node-build/client → client}/static/media/file-excel-solid.217d73db.svg +0 -0
  173. /package/{node-build/client → client}/static/media/file-pdf-solid.0a9d75fe.svg +0 -0
  174. /package/{node-build/client → client}/static/media/file-powerpoint-solid.4d969453.svg +0 -0
  175. /package/{node-build/client → client}/static/media/file-solid.6415173e.svg +0 -0
  176. /package/{node-build/client → client}/static/media/file-video-solid.312288cf.svg +0 -0
  177. /package/{node-build/client → client}/static/media/file-word-solid.9228e1ff.svg +0 -0
  178. /package/{node-build/client → client}/static/media/file-zipper-solid.7db57917.svg +0 -0
  179. /package/{node-build/client → client}/static/media/globe-africa-solid.0ad34146.svg +0 -0
  180. /package/{node-build/client → client}/static/media/link-solid.7b689dbd.svg +0 -0
  181. /package/{node-build/client → client}/static/media/open-sans-all-400-normal.cb2542fc.woff +0 -0
  182. /package/{node-build/client → client}/static/media/open-sans-all-700-normal.105e4309.woff +0 -0
  183. /package/{node-build/client → client}/static/media/open-sans-all-800-normal.86e783c7.woff +0 -0
  184. /package/{node-build/client → client}/static/media/open-sans-cyrillic-400-normal.5a546777.woff2 +0 -0
  185. /package/{node-build/client → client}/static/media/open-sans-cyrillic-700-normal.2cf6253f.woff2 +0 -0
  186. /package/{node-build/client → client}/static/media/open-sans-cyrillic-800-normal.41902933.woff2 +0 -0
  187. /package/{node-build/client → client}/static/media/open-sans-cyrillic-ext-400-normal.01b11c56.woff2 +0 -0
  188. /package/{node-build/client → client}/static/media/open-sans-cyrillic-ext-700-normal.00b4dd17.woff2 +0 -0
  189. /package/{node-build/client → client}/static/media/open-sans-cyrillic-ext-800-normal.2c1c4cc5.woff2 +0 -0
  190. /package/{node-build/client → client}/static/media/open-sans-greek-400-normal.3064bf7e.woff2 +0 -0
  191. /package/{node-build/client → client}/static/media/open-sans-greek-700-normal.a0312547.woff2 +0 -0
  192. /package/{node-build/client → client}/static/media/open-sans-greek-800-normal.d60c6496.woff2 +0 -0
  193. /package/{node-build/client → client}/static/media/open-sans-greek-ext-400-normal.1ed998a4.woff2 +0 -0
  194. /package/{node-build/client → client}/static/media/open-sans-greek-ext-700-normal.8850c90c.woff2 +0 -0
  195. /package/{node-build/client → client}/static/media/open-sans-greek-ext-800-normal.fe3583f2.woff2 +0 -0
  196. /package/{node-build/client → client}/static/media/open-sans-hebrew-400-normal.daafcec8.woff2 +0 -0
  197. /package/{node-build/client → client}/static/media/open-sans-hebrew-700-normal.3befb44d.woff2 +0 -0
  198. /package/{node-build/client → client}/static/media/open-sans-hebrew-800-normal.bfe88fed.woff2 +0 -0
  199. /package/{node-build/client → client}/static/media/open-sans-latin-400-normal.a1535f45.woff2 +0 -0
  200. /package/{node-build/client → client}/static/media/open-sans-latin-700-normal.b245bc85.woff2 +0 -0
  201. /package/{node-build/client → client}/static/media/open-sans-latin-800-normal.185f6b03.woff2 +0 -0
  202. /package/{node-build/client → client}/static/media/open-sans-latin-ext-400-normal.ccfa20f8.woff2 +0 -0
  203. /package/{node-build/client → client}/static/media/open-sans-latin-ext-700-normal.64471a17.woff2 +0 -0
  204. /package/{node-build/client → client}/static/media/open-sans-latin-ext-800-normal.988eae1a.woff2 +0 -0
  205. /package/{node-build/client → client}/static/media/open-sans-vietnamese-400-normal.473f6b09.woff2 +0 -0
  206. /package/{node-build/client → client}/static/media/open-sans-vietnamese-700-normal.b4c5968d.woff2 +0 -0
  207. /package/{node-build/client → client}/static/media/open-sans-vietnamese-800-normal.27b69d87.woff2 +0 -0
  208. /package/{node-build/client → client}/static/media/search-solid.cc51b702.svg +0 -0
  209. /package/{node-build/client → client}/tiro-local.crt +0 -0
  210. /package/{node-build/server → server}/ssl/tiro-local.crt +0 -0
  211. /package/{node-build/server → server}/ssl/tiro-local.key +0 -0
  212. /package/{node-build/server → server}/tiro-server.js +0 -0
  213. /package/{node-build/server → server}/tiro-server.js.LICENSE.txt +0 -0
  214. /package/{node-build/shared.helpers.build.js → shared.helpers.build.js} +0 -0
@@ -1,956 +0,0 @@
1
- #include <WiFi.h>
2
- #include <HTTPClient.h>
3
- #include <M5Unified.h>
4
- #include <esp_sleep.h>
5
- #include <vector>
6
- #include <string>
7
- #include <SD.h>
8
- #include <ArduinoJson.h>
9
- // if files ending w rec appears >> format fat32 4k size Format the SD card to FAT32 with 4096-byte allocation unit size
10
- // sudo chmod a+rw /dev/ttyACM0
11
- // Wi-Fi Configuration
12
- #define WIFI_SSID "42" // Replace with your SSID
13
- #define WIFI_PASSWORD "87345678" // Replace with your password
14
-
15
- // API endpoint (dynamically constructed using gateway IP and port 3023)
16
- String getApiUrl(String type) {
17
- IPAddress gateway = WiFi.gatewayIP();
18
- String endpointWithType = "m5epaper-endpoint&id=" + type;
19
- String args1 = "custom_backend_api?file=" + endpointWithType + "&token=796a01190502a2a92c38926dafcb10269d6cb3f7a9a6413218468614730d31c0089d8c42b92c53140f597020c6afaca1d9e2c1d8bb2d4fea98a3d90d6a80016ac1341e4275e18587e7a090a91cfdc2c2";
20
- String url = "http://" + gateway.toString() + ":3023/" + args1;
21
- return url;
22
- }
23
-
24
- // Define the main power pin for M5Paper
25
- #define M5EPD_MAIN_PWR_PIN 21
26
- // Deep sleep duration (5 minutes in microseconds)
27
- #define DEEPSLEEPMIN 5
28
- #define DEEP_SLEEP_DURATION_DELAY (DEEPSLEEPMIN * 60 * 1000 * 1000)
29
- #define MARGIN 20
30
- // Maximum retries for API fetch
31
- #define MAX_RETRIES 3
32
- #define RETRY_DELAY_MS 2000
33
-
34
- // Button pins
35
- #define BUTTON_UP_PIN 37
36
- #define BUTTON_DOWN_PIN 39
37
- #define BUTTON_PRESS_PIN 38
38
- // long press down
39
- #define BUTTON_LONG_PRESS_DURATION 2000
40
-
41
- // Page settings
42
- // const GFXfont* currentFont = &fonts::FreeSansBold12pt7b;
43
- // const GFXfont* currentFont = &fonts::FreeSans12pt7b;
44
-
45
- std::vector<String> pages;
46
- int currentPage = 0;
47
- String cfont = "sans-bold-12";
48
- bool shouldWrapText = false;
49
- int maxCharsPerPage = 1200;
50
- String currentContentType = "0";
51
- // Add these global variables
52
- SemaphoreHandle_t spiBusMutex;
53
-
54
- ///////////////////////////////////////////////////////
55
- //
56
- //
57
- // FUNCTIONS
58
- //
59
- //
60
-
61
- /////////////////////////////////////////////
62
- //
63
- // SDCARD
64
- //
65
-
66
- #define SD_SPI_SCK_PIN 14
67
- #define SD_SPI_MISO_PIN 13
68
- #define SD_SPI_MOSI_PIN 12
69
- #define SD_SPI_CS_PIN 4
70
-
71
-
72
- // JSON document capacity (adjust based on your data size)
73
-
74
-
75
- // Save a raw string to SD card cache
76
- bool setCache(const char* cacheId, const String& data) {
77
- if (xSemaphoreTake(spiBusMutex, portMAX_DELAY) != pdTRUE) {
78
- return false;
79
- }
80
- char filename[32];
81
- snprintf(filename, sizeof(filename), "/cache-%s.txt", cacheId);
82
-
83
- // Check if SD card is initialized first
84
- if (!SD.cardType()) {
85
- M5.Display.printf("!!! setCache >> SD card not initialized\n");
86
- delay(3000);
87
- return false;
88
- }
89
-
90
- // Open file for write, truncate existing content
91
- File file = SD.open(filename, FILE_WRITE, true);
92
- delay(100);
93
- if (!file) {
94
- // M5.Display.setCursor(0, 0);
95
- M5.Display.printf("!!! setCache >> Open %s failed\n", filename);
96
- delay(1000);
97
- // initSDcard(); // Try to reinitialize SD card
98
- return false;
99
- }
100
-
101
- size_t bytesWritten = file.print(data);
102
- delay(100);
103
- // Ensure all data is flushed before closing
104
-
105
- // Flush and close with error checking
106
- delay(100);
107
- file.flush();
108
- delay(100);
109
- file.close();
110
-
111
- if (bytesWritten != data.length()) {
112
- M5.Display.setCursor(0, 20);
113
- M5.Display.printf("!!! setCache >> Partial write: %d/%d bytes", bytesWritten, data.length());
114
- return false;
115
- }
116
-
117
- M5.Display.printf("[OK] setCache >> Saved to %s\n", filename);
118
- xSemaphoreGive(spiBusMutex);
119
- return true;
120
- }
121
-
122
- // Load a raw string from SD card cache
123
- String getCache(const char* cacheId) {
124
- char filename[32];
125
- snprintf(filename, sizeof(filename), "/cache-%s.txt", cacheId);
126
- // sleep for 150ms
127
- delay(150);// sleep for 150ms
128
-
129
- File file = SD.open(filename, FILE_READ);
130
- if (!file) {
131
- M5.Display.printf("!!! getCache >> File %s not found\n", filename);
132
- return "";
133
- }
134
-
135
- String content = "";
136
- while (file.available()) {
137
- content += (char)file.read();
138
- }
139
- file.close();
140
-
141
- if (content.length() == 0) {
142
- M5.Display.println("getCache >> Cache file is empty");
143
- } else {
144
- M5.Display.printf("getCache >> SD CARD CACHE > found and loading %d bytes\n", content.length());
145
- }
146
- return content;
147
- }
148
-
149
- bool deleteCache(const char* cacheId) {
150
- char filename[32];
151
- snprintf(filename, sizeof(filename), "/cache-%s.txt", cacheId);
152
- delay(200);
153
-
154
- // Check if file exists first
155
- if (!SD.exists(filename)) {
156
- M5.Display.printf("!!! deleteCache >> Cache %s not found\n", cacheId);
157
- return false;
158
- }
159
-
160
- // Delete the file
161
- if (SD.remove(filename)) {
162
- M5.Display.printf("deleteCache >> Deleted cache: %s\n", cacheId);
163
- return true;
164
- } else {
165
- M5.Display.printf("!!! deleteCache >> Delete %s failed\n", cacheId);
166
- return false;
167
- }
168
- }
169
-
170
- // Updated init with safer clock speed
171
- bool initSDcard() {
172
- // In setup()
173
- spiBusMutex = xSemaphoreCreateMutex();
174
-
175
- // Ensure SD card power is stable
176
- M5.Power.setExtOutput(false); // Enable 5V power for SD card
177
- delay(200); // Wait for power to stabilize
178
- M5.Power.setExtOutput(true); // Enable 5V power for SD card
179
- delay(100); // Wait for power to stabilize
180
-
181
- SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN);
182
-
183
- // Use 5MHz clock (M5Paper's recommended speed)
184
- for (int attempts = 0; attempts < 3; attempts++) {
185
- if (SD.begin(SD_SPI_CS_PIN, SPI, 5*1000*1000)) {
186
- M5.Display.println("SD card initialized successfully");
187
- return true;
188
- }
189
- delay(500);
190
- }
191
- M5.Display.println("SD card initialization failed after 3 attempts");
192
- return false;
193
- }
194
- // void initSDcard(){
195
- // SPI.begin(SD_SPI_SCK_PIN, SD_SPI_MISO_PIN, SD_SPI_MOSI_PIN, SD_SPI_CS_PIN);
196
- // int sd_init_attempts = 0;
197
- // while (!SD.begin(SD_SPI_CS_PIN, SPI, 25 * 1000 * 1000) && sd_init_attempts < 3) {
198
- // delay(500);
199
- // sd_init_attempts++;
200
- // }
201
-
202
- // // if (!SD.begin(SD_SPI_CS_PIN, SPI, 5000000)) {
203
- // // M5.Display.println("!!! SD init failed!");
204
- // // while (1);
205
- // // }
206
- // }
207
-
208
- /////////////////////////////////////////////
209
- //
210
- // JSON
211
- //
212
-
213
- String getJsonParam(const String& jsonString, const String& key) {
214
- DynamicJsonDocument doc(131072); // 128KB buffer
215
- DeserializationError error = deserializeJson(doc, jsonString);
216
- if (error) {
217
- // show first 30 chars of jsonString
218
- String jsonSnippet = jsonString.substring(0, 30);
219
- M5.Display.printf("!!! JSON parse error: %s...\n", jsonSnippet.c_str());
220
- sleep(3000);
221
- return "";
222
- }
223
- if (doc.containsKey(key)) {
224
- return doc[key].as<String>();
225
- } else {
226
- M5.Display.printf("!!! Key %s not found in JSON\n", key.c_str());
227
- return "";
228
- }
229
- }
230
- bool setJsonParam(const String& jsonString, const String& key, const String& value) {
231
- DynamicJsonDocument doc(131072); // 128KB buffer
232
- DeserializationError error = deserializeJson(doc, jsonString);
233
- if (error) {
234
- M5.Display.println("!!!JSON parse error");
235
- return false;
236
- }
237
- doc[key] = value;
238
- String updatedJson;
239
- serializeJson(doc, updatedJson);
240
- // Save updated JSON back to cache
241
- return setCache("api_response", updatedJson);
242
- }
243
-
244
- /////////////////////////////////////////////
245
- //
246
- // WIFI AND CONNECTIVITY
247
- //
248
- void disconnectWifi() {
249
- // Disconnect WiFi
250
- WiFi.disconnect(true);
251
- WiFi.mode(WIFI_OFF);
252
- log("wifi disconnected");
253
- }
254
- void connectWiFi() {
255
- M5.Display.print("WiFi: ");
256
- WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
257
-
258
- int attempts = 0;
259
- while (WiFi.status() != WL_CONNECTED && attempts < 10) {
260
- M5.Display.print(".");
261
- delay(500);
262
- attempts++;
263
- }
264
-
265
- if (WiFi.status() == WL_CONNECTED) {
266
- M5.Display.println("\nConnected");
267
- M5.Display.printf("IP: %s\n", WiFi.localIP().toString().c_str());
268
- } else {
269
- M5.Display.println("\nFailed to connect");
270
- }
271
- }
272
-
273
- String fetchApiContent(String contentType) {
274
- String payload = "";
275
- bool success = false;
276
- int retryCount = 0;
277
- while (retryCount < MAX_RETRIES && !success) {
278
- M5.Display.setCursor(0, M5.Display.getCursorY());
279
- if (WiFi.status() == WL_CONNECTED) {
280
- HTTPClient http;
281
- String apiUrl = getApiUrl(contentType);
282
- M5.Display.printf("Fetching API content from: %s...\n", apiUrl.substring(0, 30).c_str());
283
- http.begin(apiUrl);
284
- http.setTimeout(10000);
285
- int httpCode = http.GET();
286
- if (httpCode > 0) {
287
- if (httpCode == HTTP_CODE_OK) {
288
- payload = http.getString();
289
- success = true;
290
- } else {
291
- M5.Display.printf("HTTP Error: %d (Retry %d/%d)\n",
292
- httpCode, retryCount + 1, MAX_RETRIES);
293
- }
294
- } else {
295
- M5.Display.printf("HTTP GET failed: %s (Retry %d/%d)\n",
296
- http.errorToString(httpCode).c_str(),
297
- retryCount + 1, MAX_RETRIES);
298
- }
299
- http.end();
300
- } else {
301
- M5.Display.println("WiFi not connected!");
302
- }
303
- if (!success) {
304
- retryCount++;
305
- if (retryCount < MAX_RETRIES) {
306
- delay(RETRY_DELAY_MS);
307
- }
308
- }
309
- }
310
- if (success) {
311
- int lineCount = 0;
312
- int lastPos = 0;
313
- int currentPos = 0;
314
- while (lineCount < 4 && currentPos != -1) {
315
- currentPos = payload.indexOf('\n', lastPos);
316
- if (currentPos != -1) {
317
- lastPos = currentPos + 1;
318
- lineCount++;
319
- }
320
- }
321
- if (lastPos < payload.length()) {
322
- String remainingContent = payload.substring(lastPos);
323
- remainingContent = remainingContent;
324
- remainingContent.replace("\n", "\n ");
325
- remainingContent = " " + remainingContent;
326
- return remainingContent;
327
- }
328
- }
329
- return "";
330
- }
331
-
332
- void splitContentIntoPages(String content) {
333
- pages.clear();
334
- currentPage = 0;
335
-
336
- int startPos = 0;
337
- while (startPos < content.length()) {
338
- int endPos = startPos + maxCharsPerPage;
339
- if (endPos >= content.length()) {
340
- pages.push_back(content.substring(startPos));
341
- break;
342
- }
343
-
344
- // Find the last space before maxCharsPerPage to avoid word breaks
345
- int lastSpace = content.lastIndexOf(' ', endPos);
346
- if (lastSpace > startPos) {
347
- endPos = lastSpace;
348
- }
349
-
350
- pages.push_back(content.substring(startPos, endPos));
351
- startPos = endPos + 1;
352
- }
353
- }
354
-
355
-
356
-
357
- ////////////////////////////////////
358
- //
359
- // Draw wrapped text
360
-
361
- // Splits text into wrapped lines (returns vector of lines)
362
- std::vector<String> wrapText(const String& text, int maxWidth) {
363
- std::vector<String> lines;
364
- const lgfx::v1::IFont* font = M5.Display.getFont();
365
- int currentLineWidth = 0;
366
- String currentLine = "";
367
- String currentWord = "";
368
-
369
- for (char c : text) {
370
- if (c == ' ' || c == '\n') {
371
- // Process current word
372
- int wordWidth = M5.Display.textWidth(currentWord.c_str(), font);
373
- if (currentLineWidth + wordWidth > maxWidth) {
374
- lines.push_back(currentLine); // Add previous line
375
- currentLine = currentWord; // Start new line with current word
376
- currentLineWidth = wordWidth;
377
- } else {
378
- currentLine += currentWord; // Add word to current line
379
- currentLineWidth += wordWidth;
380
- }
381
-
382
- // Process space or newline
383
- if (c == ' ') {
384
- int spaceWidth = M5.Display.textWidth(" ", font);
385
- if (currentLineWidth + spaceWidth > maxWidth) {
386
- lines.push_back(currentLine);
387
- currentLine = "";
388
- currentLineWidth = 0;
389
- } else {
390
- currentLine += " ";
391
- currentLineWidth += spaceWidth;
392
- }
393
- } else { // Newline
394
- lines.push_back(currentLine);
395
- currentLine = "";
396
- currentLineWidth = 0;
397
- }
398
- currentWord = "";
399
- } else {
400
- currentWord += c; // Build current word
401
- }
402
- }
403
-
404
- // Add remaining word/line
405
- if (currentWord.length() > 0) {
406
- int wordWidth = M5.Display.textWidth(currentWord.c_str(), font);
407
- if (currentLineWidth + wordWidth > maxWidth) {
408
- lines.push_back(currentLine);
409
- currentLine = currentWord;
410
- } else {
411
- currentLine += currentWord;
412
- }
413
- lines.push_back(currentLine);
414
- }
415
-
416
- return lines;
417
- }
418
-
419
- // Prints wrapped lines (one per line)
420
- void drawWrappedText2(const String& text, int x, int y, int maxWidth) {
421
- std::vector<String> lines = wrapText(text, maxWidth);
422
- int lineHeight = M5.Display.fontHeight(M5.Display.getFont());
423
- int currentY = y;
424
-
425
- for (const String& line : lines) {
426
- M5.Display.setCursor(x, currentY);
427
- M5.Display.print(line); // Print entire line at once
428
- currentY += lineHeight;
429
- }
430
- }
431
-
432
- // // const GFXfont* currentFont = &fonts::FreeSansBold12pt7b;
433
- // const GFXfont* currentFont = &fonts::FreeSans12pt7b;
434
- //
435
-
436
- void displayCurrentPage() {
437
- M5.Display.clear();
438
- M5.Display.setCursor(0, 0);
439
-
440
- //
441
- // FONTS MANAGEMENT
442
- //
443
- bool showFooter = true;
444
- if (cfont == "utf8-24") {
445
- M5.Display.setFont(&fonts::lgfxJapanMinchoP_24);
446
- shouldWrapText = true;
447
- }
448
- // 12 32 40
449
- if (cfont == "utf8-12") {
450
- M5.Display.setFont(&fonts::lgfxJapanMinchoP_12);
451
- shouldWrapText = true;
452
- }
453
- if (cfont == "utf8-32") {
454
- M5.Display.setFont(&fonts::lgfxJapanMinchoP_32);
455
- shouldWrapText = true;
456
- showFooter = false;
457
- }
458
- if (cfont == "utf8-40") {
459
- M5.Display.setFont(&fonts::lgfxJapanMinchoP_40);
460
- shouldWrapText = true;
461
- showFooter = false;
462
- }
463
-
464
- if (cfont == "sans-12") {
465
- M5.Display.setFont(&fonts::FreeSans12pt7b);
466
- shouldWrapText = true;
467
- }
468
- if (cfont == "sans-bold-12") {
469
- M5.Display.setFont(&fonts::FreeSansBold12pt7b);
470
- shouldWrapText = true;
471
- }
472
- if (cfont == "sans-bold-24") {
473
- M5.Display.setFont(&fonts::FreeSansBold24pt7b);
474
- shouldWrapText = true;
475
- showFooter = false;
476
- }
477
- if (cfont == "sans-24") {
478
- M5.Display.setFont(&fonts::FreeSans24pt7b);
479
- shouldWrapText = true;
480
- showFooter = false;
481
- }
482
- // 18
483
- if (cfont == "sans-bold-18") {
484
- M5.Display.setFont(&fonts::FreeSansBold18pt7b);
485
- shouldWrapText = true;
486
- showFooter = false;
487
- }
488
- if (cfont == "sans-18") {
489
- M5.Display.setFont(&fonts::FreeSans18pt7b);
490
- shouldWrapText = true;
491
- }
492
-
493
-
494
- M5.Display.setTextWrap(true);
495
- if (pages.size() > 0) {
496
- if (shouldWrapText) {
497
- drawWrappedText2(pages[currentPage], MARGIN, MARGIN, M5.Display.width() - (MARGIN*2));
498
- } else {
499
- M5.Display.print(pages[currentPage]);
500
- }
501
- if (showFooter == true) {
502
- M5.Display.setCursor(0, M5.Display.height() - MARGIN - 20);
503
- M5.Display.printf("Page %d/%d | batt %d | %s", currentPage + 1, pages.size(), M5.Power.getBatteryLevel(), currentContentType.c_str());
504
- }
505
- } else {
506
- M5.Display.println("No content available");
507
- }
508
- M5.Display.display();
509
- }
510
-
511
- void goToPage(int page, bool updatePage) {
512
- if (page >= 0 && page < pages.size()) {
513
- currentPage = page;
514
- if (updatePage == true) {
515
- // setCache("epaper-page-content", String(page));
516
- setCache((String("epaper-page-") + currentContentType).c_str(), String(page));
517
- }
518
- // setCache((String("epaper-page-") + contentType).c_str(), String(page));
519
- displayCurrentPage();
520
- }
521
- }
522
-
523
- void nextPage() {
524
- goToPage(currentPage + 1, true);
525
- }
526
-
527
- void previousPage() {
528
- goToPage(currentPage - 1, true);
529
- }
530
-
531
-
532
- String ensureUTF8(const String& input) {
533
- String utf8Str;
534
- utf8Str.reserve(input.length() * 2); // Preallocate space
535
- for (char c : input) {
536
- uint8_t byte = static_cast<uint8_t>(c);
537
- if (byte < 0x80) {
538
- utf8Str += c; // ASCII
539
- } else {
540
- // Convert Latin-1 (ISO-8859-1) to UTF-8
541
- utf8Str += static_cast<char>(0xC2); // Leading byte for 0x80-0xBF
542
- utf8Str += static_cast<char>(byte);
543
- }
544
- }
545
- return utf8Str;
546
- }
547
-
548
-
549
-
550
-
551
-
552
-
553
-
554
-
555
-
556
-
557
-
558
- ///////////////////////////////////////////////////////
559
- //
560
- //
561
- // EXECUTION SCENARIOS
562
- //
563
- //
564
-
565
- bool SCENARIO_tryfetch(String contentType, bool toggleWifi) {
566
- // M5.Display.setFont(&fonts::FreeSans12pt7b);
567
- if(fetchContentWifi(contentType, toggleWifi)) {
568
- return true;
569
- } else {
570
- log("Second attempt failed. coming back to menu");
571
- SCENARIO_toggleMenu();
572
- delay(2000);
573
- return false;
574
- }
575
- // if (fetchContentWifi(contentType, toggleWifi)) {
576
- // return true;
577
- // } else {
578
- // // sleep 3 seconds
579
- // M5.Display.setCursor(0, 0);
580
- // M5.Display.clear();
581
- // M5.Display.println("Failed to fetch content, retrying...");
582
- // delay(2000);
583
- // if (fetchContentWifi(contentType, toggleWifi)) {
584
- // return true;
585
- // } else {
586
- // M5.Display.println("Second attempt failed. coming back to menu");
587
- // delay(2000);
588
- // SCENARIO_toggleMenu();
589
-
590
- // }
591
-
592
- // }
593
- }
594
-
595
-
596
- bool fetchApi_andSave(String contentType){
597
- bool answer = false;
598
- // Fetch and prepare content
599
- String content = fetchApiContent(contentType);
600
- if (content.length() > 0) {
601
- String contentSub = content.substring(0, 100); // Get first 100 characters
602
- M5.Display.println("Content fetched, saving to cache..." + contentSub);
603
- delay(100);
604
- bool res1 = setCache((String("epaper-display-") + contentType).c_str(), content);
605
- String result = getJsonParam(content, "result");
606
- int page = getJsonParam(result, "page").toInt();
607
- if (page != 0) {
608
- setCache((String("epaper-page-") + contentType).c_str(), String(page));
609
- }
610
- String font = getJsonParam(result, "font");
611
- setCache((String("epaper-font-") + contentType).c_str(), font);
612
- int maxCharsPerPage = getJsonParam(result, "maxCharsPerPage").toInt();
613
- setCache((String("epaper-maxCharsPerPage-") + contentType).c_str(), String(maxCharsPerPage));
614
- M5.Display.setCursor(0, 0);
615
- M5.Display.clear();
616
- if (res1) {
617
- answer = true;
618
- M5.Display.println("content saved successfully, Loading it... " + String(answer));
619
- } else {
620
- M5.Display.println("Failed to save content");
621
- delay(100);
622
- }
623
- delay(100);
624
- } else {
625
- M5.Display.println("No content available");
626
- M5.Display.display();
627
- }
628
- return answer;
629
- }
630
-
631
- bool fetchContentWifi(String contentType, bool toggleWifi) {
632
-
633
- bool answer = false;
634
- if (toggleWifi) { connectWiFi(); }
635
- bool answer1 = fetchApi_andSave(contentType);
636
- answer = answer1;
637
- if (toggleWifi) { disconnectWifi(); }
638
- return answer;
639
- }
640
-
641
- void cacheFoundSd_displayIt(String contentType){
642
- // String cachedJson = getCache("epaper-display-"+contentType);
643
- String cachedJson = getCache((String("epaper-display-") + contentType).c_str());
644
- if (cachedJson.length() > 0) {
645
- String result = getJsonParam(cachedJson, "result");
646
- String content = getJsonParam(result, "content");
647
-
648
- M5.Display.println("Displaying cached content");
649
- splitContentIntoPages(content);
650
- // get page
651
- // int page = getCache("epaper-page-"+contentType).toInt();
652
- int page = getCache((String("epaper-page-") + contentType).c_str()).toInt();
653
- // get font
654
- cfont = getCache((String("epaper-font-") + contentType).c_str());
655
- // get maxCharsPerPage
656
- maxCharsPerPage = getCache((String("epaper-maxCharsPerPage-") + contentType).c_str()).toInt();
657
- // skip page update
658
- goToPage(page, false);
659
- } else {
660
- M5.Display.println("Cached content is empty");
661
- }
662
- }
663
-
664
-
665
- void SCENARIO_fetchAll() {
666
- connectWiFi();
667
- for (int i = 0; i <= 10; i++) {
668
- SCENARIO_tryfetch(String(i), false);
669
- }
670
- disconnectWifi();
671
- SCENARIO_toggleMenu();
672
- }
673
-
674
- void SCENARIO_removeAllCache() {
675
- for (int i = 0; i <= 10; i++) {
676
- removeCacheContent(String(i));
677
- }
678
- log("All cache cleared");
679
- SCENARIO_toggleMenu();
680
-
681
- }
682
-
683
- void log(String message) {
684
- // bottom
685
- int pheight = M5.Display.getCursorY();
686
- M5.Display.setCursor(0, 0);
687
- M5.Display.println("___________________________________________");
688
- M5.Display.setCursor(0, 0);
689
- M5.Display.println(">> " + message);
690
- }
691
-
692
- void removeCacheContent(String contentType) {
693
- deleteCache((String("epaper-display-") + contentType).c_str());
694
- // deleteCache((String("epaper-page-") + contentType).c_str());
695
- // deleteCache((String("epaper-font-") + contentType).c_str());
696
- // deleteCache((String("epaper-maxCharsPerPage-") + contentType).c_str());
697
- }
698
-
699
-
700
-
701
-
702
-
703
-
704
-
705
-
706
-
707
-
708
-
709
-
710
-
711
-
712
-
713
-
714
-
715
-
716
-
717
- ///////////////////////////////////////////////////////
718
- //
719
- //
720
- // TOGGLE MENU SCENARIO
721
- //
722
- //
723
-
724
-
725
- bool isMenuVisible = false;
726
- int topBarHeight = 50;
727
- int menuItemHeight = 50;
728
- int paddingMenuTop = 100;
729
-
730
- void p (String message){
731
- M5.Display.println(message);
732
- }
733
-
734
- void SCENARIO_toggleMenu() {
735
- if (isMenuVisible) {
736
- isMenuVisible = false;
737
- displayCurrentPage();
738
- } else {
739
- SCENARIO_showMenu();
740
- }
741
- }
742
-
743
- struct MenuOption {
744
- String label;
745
- void (*action)();
746
- };
747
- MenuOption menuOptions[] = {
748
- {"content 1", []() { SCENARIO_displayContent_else_fetch("1"); }},
749
- {"content 2", []() { SCENARIO_displayContent_else_fetch("2"); }},
750
- {"content 3", []() { SCENARIO_displayContent_else_fetch("3"); }},
751
- {"content 4", []() { SCENARIO_displayContent_else_fetch("4"); }},
752
- {"content 5", []() { SCENARIO_displayContent_else_fetch("5"); }},
753
- {"content 6", []() { SCENARIO_displayContent_else_fetch("6"); }},
754
- {"content 7", []() { SCENARIO_displayContent_else_fetch("7"); }},
755
- {"content 8", []() { SCENARIO_displayContent_else_fetch("8"); }},
756
- {"content 9", []() { SCENARIO_displayContent_else_fetch("9"); }},
757
- {"content 10", []() { SCENARIO_displayContent_else_fetch("10"); }},
758
- {"fetch all", []() { SCENARIO_fetchAll(); }},
759
-
760
- {"delete all", []() { SCENARIO_removeAllCache(); }}
761
- };
762
- void SCENARIO_showMenu() {
763
-
764
- // clean display and every 100 height, show option
765
- isMenuVisible = true;
766
- M5.Display.clear();
767
-
768
- for (int i = 0; i < sizeof(menuOptions) / sizeof(MenuOption); i++) {
769
- M5.Display.setCursor(50, topBarHeight + paddingMenuTop + (i * menuItemHeight));
770
- M5.Display.printf("%d. %s\n", i + 1, menuOptions[i].label.c_str());
771
- }
772
-
773
- M5.Display.display();
774
- }
775
-
776
- void SCENARIO_loop_menuTouch(){
777
- if (!isMenuVisible) return;
778
-
779
- auto touch = M5.Touch.getDetail();
780
- if (touch.isPressed() &&
781
- touch.y >= topBarHeight
782
- ) {
783
- int touchY = touch.y;
784
- int optionIndex = (touchY - topBarHeight - paddingMenuTop) / menuItemHeight; // Assuming each option is 50px high
785
- if (optionIndex >= 0 && optionIndex < sizeof(menuOptions) / sizeof(MenuOption)) {
786
- M5.Display.setCursor(0, 0);
787
- M5.Display.println("[Touch detected in menu] =>" + menuOptions[optionIndex].label);
788
- menuOptions[optionIndex].action();
789
- isMenuVisible = false;
790
- // displayCurrentPage();
791
- }
792
- }
793
-
794
- }
795
-
796
- void SCENARIO_displayContent_else_fetch(String contentType) {
797
- currentContentType = contentType;
798
- if (getCache((String("epaper-display-") + contentType).c_str()).length() == 0) {
799
- SCENARIO_tryfetch(contentType, true);
800
- cacheFoundSd_displayIt(contentType);
801
- } else {
802
- cacheFoundSd_displayIt(contentType);
803
- }
804
- }
805
-
806
- ///////////////////////////////////////////////////////
807
- //
808
- //
809
- // EXECUTION LOOP
810
- //
811
- //
812
- // start time for deep sleep delay
813
- unsigned long deepSleepStartTime;
814
-
815
- void setup() {
816
- M5.begin();
817
- deepSleepStartTime = millis();
818
- M5.Display.setRotation(0);
819
- // init font
820
- M5.Display.setFont(&fonts::FreeSans12pt7b);
821
- // M5.Display.setEpdMode(epd_fast);
822
-
823
-
824
- // POWER > low energey mode test
825
- M5.Display.setEpdMode(epd_text);
826
- M5.Display.println("APP STARTED");
827
- // Initialize buttons
828
- pinMode(BUTTON_UP_PIN, INPUT_PULLUP);
829
- pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP);
830
- pinMode(BUTTON_PRESS_PIN, INPUT_PULLUP);
831
-
832
- initSDcard();
833
-
834
- // POWER > SHUTDOWN WIFI AND OTHER AT SETUP
835
- WiFi.mode(WIFI_OFF);
836
- btStop();
837
- // other sensors
838
- // M5.SHT30.powerOff();
839
-
840
-
841
-
842
- // SCENARIO_displayContent_else_fetch("0");
843
- SCENARIO_toggleMenu();
844
- }
845
-
846
-
847
-
848
-
849
- // add currentTimerMs
850
- bool canTriggerTouch = true;
851
- int currentTimerMs = 0;
852
-
853
- unsigned long previousMillis = 0;
854
- const long interval = 100;
855
-
856
- void loop() {
857
- // currentTimerMs += 100;
858
- unsigned long currentMillis = millis();
859
-
860
- // POWER > NON BLOCKING CPU WAIT
861
- if (currentMillis - previousMillis >= interval) {
862
- previousMillis = currentMillis;
863
- currentTimerMs += interval;
864
-
865
- // Check buttons
866
- if (digitalRead(BUTTON_DOWN_PIN) == LOW) {
867
- nextPage();
868
- delay(200); // Debounce
869
- currentTimerMs = 0;
870
- }
871
- else if (digitalRead(BUTTON_UP_PIN) == LOW) {
872
- previousPage();
873
- delay(200); // Debounce
874
- currentTimerMs = 0;
875
- }
876
- else if (digitalRead(BUTTON_PRESS_PIN) == LOW) {
877
- startDeepSleep();
878
- currentTimerMs = 0;
879
-
880
- }
881
- // In your loop() function
882
- M5.update(); // Required for touch detection
883
-
884
- auto touch = M5.Touch.getDetail();
885
- int cornerWidth = 50; // Width of the touch area
886
- int screenWidth = M5.Display.width();
887
- int screenHeight = M5.Display.height();
888
-
889
-
890
- SCENARIO_loop_menuTouch();
891
-
892
- handleTouchZone(0, 0, cornerWidth, topBarHeight, SCENARIO_toggleMenu, false);
893
-
894
- // if more than deep sleep delay, deep sleep,
895
- if (currentTimerMs > ( 6 * 60 * 1000 )) {
896
- M5.Display.println("[Deep sleep] triggered after " + String(currentTimerMs) + " ms");
897
- startDeepSleep();
898
- }
899
- // reenable touch detection after 1 minute
900
- if (currentTimerMs > (1*60*1000)) {
901
- canTriggerTouch = true;
902
- }
903
- }
904
- // delay(100);
905
- }
906
-
907
- void handleTouchZone(int x1, int y1, int x2, int y2, void (*action)(), bool delayAfter) {
908
- auto touch = M5.Touch.getDetail();
909
- if (touch.isPressed() &&
910
- touch.x >= x1 && touch.x <= x2 &&
911
- touch.y >= y1 && touch.y <= y2 &&
912
- canTriggerTouch
913
- ) {
914
- if (delayAfter) {
915
- canTriggerTouch = false;
916
- }
917
- M5.Display.setCursor(0, 0);
918
- currentTimerMs = 0;
919
- M5.Display.println("[Touch detected in zone]");
920
- action();
921
- }
922
- }
923
-
924
-
925
-
926
- void startDeepSleep(){
927
-
928
- // UNCOMMENT THAT LINE FOR DEEPSLEEP SCREEN
929
- // DISPLAY deepsleep_screen
930
-
931
-
932
- // OLD WAY
933
- M5.Display.setFont(&fonts::FreeSans12pt7b);
934
- shouldWrapText = true;
935
- M5.Display.setCursor(M5.Display.width() - 200, M5.Display.height() - MARGIN - 20);
936
- M5.Display.println("[deep sleep]");
937
- //M5.Display.update();
938
- delay(1000);
939
-
940
- // Configure GPIO hold to keep main power active during deep sleep
941
- gpio_hold_en((gpio_num_t)M5EPD_MAIN_PWR_PIN);
942
- gpio_deep_sleep_hold_en();
943
-
944
- // POWER Put e-ink display into low-power mode >> APPARENTLY CRITICAL as not managed by deep sleep
945
- // Reconfigure pins for deep sleep wake-up
946
- pinMode(BUTTON_PRESS_PIN, INPUT); // Remove pull-up
947
- pinMode(BUTTON_UP_PIN, INPUT); // Remove pull-up
948
- pinMode(BUTTON_DOWN_PIN, INPUT); // Remove pull-up
949
- M5.Display.sleep();
950
- WiFi.mode(WIFI_OFF);
951
- btStop();
952
-
953
- // Enable button wake-up >> STILL DOES NOT WORK
954
- esp_sleep_enable_ext0_wakeup(GPIO_NUM_37, LOW);
955
- M5.Power.powerOff();
956
- }