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