Skip to content

Commit

Permalink
Added screensaver and threadwatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
rebane2001 committed Oct 24, 2020
1 parent 02ad4e0 commit 1f0bf41
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 13 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Chanduino is a standalone unofficial 4chan browser for the ESP32 (TTGO T-Display
- Zoom into images (fullscreen)
- Compact UI styled after Yotsuba/Yotsuba B
- Multi-screen posts (if there is too much text for one screen)
- Screensaver (turn off screen after inactivity)
- Threadwatcher (turn on screen on new posts)
- HTTPS and keep-alive support
- Doesn't let you respond to bait
- Doesn't crash most of the time
Expand All @@ -22,6 +24,21 @@ On first launch or if no WiFi is found, Chanduino will create a WiFi hotspot whi

Just pressing up/down buttons is self-explanatory. Holding down the up button lets you go upwards (from thread to board to boards selection). It also lets you navigate the boards selection faster. Holding the down button does the opposite (goes from boards selectin to board to thread) and also lets you view images in threads in fullscreen.

If you don't press any buttons for some time, Chanduino will turn off the screen (this can be disabled in the configuration section). If you load a thread and don't touch Chanduino for a while, it'll check for new posts from time to time and wake up the screen if new posts are found.

# Configuration
You can change some of the settings through editing `#define`s in `chanduino.ino`:
- CHANDUINO_SCREENSAVER_ENABLED 0/1
- Turn screensaver on/off
- CHANDUINO_SCREENSAVER_TIME 45
- Change how long until screen turns off (seconds)
- CHANDUINO_THREADWATCHER_ENABLED 0/1
- Turn threadwatcher on/off
- CHANDUINO_THREADWATCHER_TIME 60
- Change how often threadwatcher should check for new posts (seconds)
- CHANDUINO_DEFAULTBOARD "/replaceme/"
- Auto-select a board of your choice on startup

# Dependencies
- [ArduinoJson 6.16.1](https://arduinojson.org/)
- [TFT_eSPI 1.4.20](https://github.com/Bodmer/TFT_eSPI)
Expand Down
153 changes: 140 additions & 13 deletions chanduino/chanduino.ino
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,15 @@
#define BUTTON_1 35
#define BUTTON_2 0

// Set ENABLED to 1 to turn backlight off after TIME seconds of inactivity (no new posts and no button presses)
#define CHANDUINO_SCREENSAVER_ENABLED 1
#define CHANDUINO_SCREENSAVER_TIME 45
// Set to 1 to enable threadwatcher
// Set ENABLED to 1 to watch thread every TIME seconds after last buttonpress (DO NOT set under 10, recommended values are 30-120)
#define CHANDUINO_THREADWATCHER_ENABLED 1
#define CHANDUINO_THREADWATCHER_TIME 60
// Change this to your favorite board to have it auto-selected
#define CHANDUINO_DEFAULTBOARD '/replaceme/'
#define CHANDUINO_DEFAULTBOARD "/replaceme/"

TFT_eSPI tft = TFT_eSPI(135, 240); // Invoke custom library
Button2 btn1(BUTTON_1);
Expand Down Expand Up @@ -107,9 +114,19 @@ int bgcolor = 0xD6DE; //0xF71A
* 2 - Browse threads in board
* 3 - Browse boards
*/
int viewMode = 1;
int viewMode = 3;
int wifiMode = 0;

// Threadwatcher stuff
// Timestamp of last buttonpress
int64_t lastBtnPress = 0;
// Timestamp of last threadrefresh
int64_t lastRefresh = 0;
int lastReadReply = 0;
int newPostCount = 0;
bool seenAllNewPosts = true;
int oldReplies[2001];

// Board list cache
std::vector<String> boards_ds;
std::vector<bool> boards_ws;
Expand All @@ -127,6 +144,7 @@ WiFiClientSecure client;
void button_init() {
// UP button
btn1.setReleasedHandler([](Button2 & b) {
updateLastTimes();
if (wifiMode == 0) {
if (connect_wifi()) {
unsigned int time = b.wasPressedFor();
Expand All @@ -152,9 +170,7 @@ void button_init() {
if (viewMode == 1) {
viewMode = 2;
restorePosts();
//load_posts();
load_reply();
//load_threads();
} else if (viewMode == 2) {
viewMode = 3;
bgcolor = 0x2104; //light 0x2104 dark 0x18C3 green 0x554A red 0xDAAA
Expand Down Expand Up @@ -187,6 +203,7 @@ void button_init() {

// DOWN button
btn2.setReleasedHandler([](Button2 & b) {
updateLastTimes();
if (wifiMode == 0) {
if (connect_wifi()) {
unsigned int time = b.wasPressedFor();
Expand All @@ -211,15 +228,19 @@ void button_init() {
if (viewMode == 1) {
draw_img(1);
} else if (viewMode == 2) {
newPostCount = 0;
seenAllNewPosts = true;
thread = replies[currentreply];
savePosts();
viewMode = 1;
draw_loading_text();
load_posts();
load_reply();
} else if (viewMode == 3) {
load_board();
viewMode = 2;
Serial.println(board);
draw_loading_text();
load_posts();
load_reply();
}
Expand Down Expand Up @@ -589,6 +610,21 @@ void draw_reply(String jsonsnippet) {
}
}
}
if (seenAllNewPosts){
lastReadReply = replies[maxreply];
} else {
tft.setTextColor(0xDAAA, bgcolor);
if (replies[currentreply] == lastReadReply)
tft.setTextColor(TFT_BLACK, 0xDAAA);
tft.setTextDatum(BL_DATUM);
if (currentreply == maxreply){
seenAllNewPosts = true;
newPostCount = 0;
tft.drawString("No new posts.", 9, 125);
}else{
tft.drawString(String(newPostCount) + (newPostCount == 1 ? " new post." : " new posts."), 9, 125);
}
}
if (currentMultiPage < multiPage) {
currentreply++;
multiPage = -1;
Expand All @@ -611,13 +647,23 @@ void draw_reply_number() {
}

/**
* Loads either all threads on a board or all replies on a thread.
* Draws loading text.
*/
void load_posts() {
void draw_loading_text() {
tft.setTextSize(1);
tft.setTextDatum(MC_DATUM);
tft.setTextColor(0xD800, bgcolor);
tft.drawString("Loading...", tft.width() / 2, tft.height() / 2);
}

/**
* Loads either all threads on a board or all replies on a thread.
*/
void load_posts() {
// Wipe replies to avoid bugs
for (int i = 0; i < 2001; i++) {
replies[i] = 0;
}

Serial.print("\r\nConnecting to ");
Serial.println(host);
Expand Down Expand Up @@ -755,13 +801,6 @@ void draw_img(bool full) {
TJpgDec.drawJpg(full ? 120 - (w / 2) : 6, full ? 68 - (h / 2) : 6, PicArray, sizeof(PicArray));
}

// Not implemented as of right now
void refresh_post() {
load_posts();
load_reply();
currentreply = 0;
}

// Saves posts so we can restore the position later
void savePosts(){
for (int i = 0; i < 2001; i++) {
Expand All @@ -780,6 +819,93 @@ void restorePosts(){
maxreply = maxposts;
}

void updateLastTimes(){
lastBtnPress = esp_timer_get_time();
lastRefresh = esp_timer_get_time();
}

/**
* Check for new replies in a thread and notify.
* Code is overengineered and ugly because we
* want to handle cases where replies are deleted.
*/
void threadwatcherUpdate(){
Serial.println("Checking for new replies...");
// Save old variables and reload the posts
for (int i = 0; i < 2001; i++) {
oldReplies[i] = replies[i];
}
int oldMax = maxreply;
int oldcurrentreply = currentreply;
load_posts();
currentreply = oldcurrentreply;

// Check how many new posts
int newPostCountTemp = 0;
for (int i = 0; i <= maxreply; i++) {
bool exists = false;
for (int j = 0; j <= oldMax; j++) {
if (replies[i] == oldReplies[j]){
exists = true;
break;
}
}
if (!exists) {
newPostCountTemp++;
Serial.println("Detected new post: " + String(replies[i]) + " at ID " + String(i));
}
}

// Check if our old selected reply still exists and is the same ID
if (oldReplies[oldcurrentreply] != replies[oldcurrentreply]){
// Oh no, we couldn't find it
// Let's search for it and fallback to previous posts if we can't find it
Serial.println("Current reply has moved, investigating");
currentreply = 0;
for (int i = oldcurrentreply; i > 0; i--) {
for (int j = 0; j <= maxreply; j++) {
if (oldReplies[i] == replies[j]){
// We found a match, set it as our current reply
Serial.println("We found a match, set it as our current reply");
currentreply = j;
// If we are loading a different post than the original, disable multipage
if (replies[currentreply] != oldReplies[oldcurrentreply]){
Serial.println("Current reply deleted, loading the closest older one.");
multiPage = -1;
}
break;
}
}
if (currentreply > 0)
break;
}
}

if (newPostCountTemp > 0){
Serial.println("Found " + String(newPostCountTemp) + " new replies.");
newPostCount += newPostCountTemp;
seenAllNewPosts = false;
load_reply();
updateLastTimes();
} else {
Serial.println("Found no new replies.");
}
}

void time_loop(){
// Screensaver
if (CHANDUINO_SCREENSAVER_ENABLED && (esp_timer_get_time() - lastBtnPress) > CHANDUINO_SCREENSAVER_TIME*1000000){
digitalWrite(TFT_BL, LOW);
} else {
digitalWrite(TFT_BL, TFT_BACKLIGHT_ON);
}
// Threadwatcher
if (CHANDUINO_THREADWATCHER_ENABLED && viewMode == 1 && (esp_timer_get_time() - lastRefresh) > CHANDUINO_THREADWATCHER_TIME*1000000){
threadwatcherUpdate();
lastRefresh = esp_timer_get_time();
}
}

/* Other stuff */

void setup() {
Expand Down Expand Up @@ -833,6 +959,7 @@ void loop() {
wifiLoop();
}
button_loop();
time_loop();
}

void wifi_scan() {
Expand Down

0 comments on commit 1f0bf41

Please sign in to comment.