diff --git a/README.md b/README.md index 05fbe3e..7938c23 100644 --- a/README.md +++ b/README.md @@ -8,5 +8,6 @@ - [x] Create container - [x] Write ESP8266 client - [ ] Make port configurable -- [ ] Transfer using JSON +- [x] Transfer using JSON - [x] Correctly implement basic auth +- [ ] Use unidecode to replace non-ascii stuff in the backend diff --git a/client/client.ino b/client/client.ino index 29b2cfb..29c19e5 100644 --- a/client/client.ino +++ b/client/client.ino @@ -1,4 +1,4 @@ -// Screen libraries etc. +#include #include #include #include @@ -33,6 +33,7 @@ enum { } state = CONNECTING; int frame = 0; int buttonPushed = false; +JsonDocument departures; void ICACHE_RAM_ATTR onButtonFalling() { buttonPushed = true; @@ -54,7 +55,7 @@ void setup() { pinMode(BUTTON_PIN, INPUT_PULLUP); attachInterrupt(BUTTON_PIN, onButtonFalling, FALLING); - display.setTextColor(SSD1306_WHITE); + display.setTextColor(SSD1306_INVERSE); display.setTextSize(1); display.setCursor(0, 0); display.printf("Connecting to\n%s\n", WIFI_SSID); @@ -66,11 +67,39 @@ void setup() { */ } -void drawSpinner (int frame) { +void drawSpinner(int frame) { display.fillRect(120, 56, spinny_dims[0], spinny_dims[1], SSD1306_BLACK); display.drawBitmap(120, 56, spinny[frame % spinny_dims[2]], spinny_dims[0], spinny_dims[1], SSD1306_WHITE); } +// TODO: Error handling +String fetchDepartures() { + std::unique_ptr https(new BearSSL::WiFiClientSecure); + https->setInsecure(); + + HTTPClient client; + if (!client.begin(*https, "vrnp.beany.club", 443, "/departures?stop_id=de:08221:1225&platform=A")) { + display.clearDisplay(); + display.setCursor(0, 0); + display.print("begin failed"); + display.display(); + for (;;); + } + + client.addHeader("Authorization", AUTH_TOKEN); + client.addHeader("Accept", "application/json"); + int statusCode = client.GET(); + if (statusCode != 200) { + display.clearDisplay(); + display.setCursor(0, 0); + display.printf("http non-ok: %d\n", statusCode); + display.display(); + for (;;); + } + + return client.getString(); +} + void loop() { switch (state) { case CONNECTING: { @@ -82,40 +111,16 @@ void loop() { } display.clearDisplay(); - display.setCursor(0, 0); - display.print("Connected!\nRequesting departures"); + display.fillRect(0, 56, 128, 8, SSD1306_INVERSE); + display.setCursor(0, 56); + display.print("requesting departures"); display.display(); - std::unique_ptr https(new BearSSL::WiFiClientSecure); - https->setInsecure(); - HTTPClient client; - if (!client.begin(*https, "vrnp.beany.club", 443, "/departures?stop_id=de:08221:1225&platform=A")) { - display.clearDisplay(); - display.setCursor(0, 0); - display.print("begin failed"); - display.display(); - for (;;); - return; - } - - client.addHeader("Authorization", AUTH_TOKEN); - int statusCode = client.GET(); - if (statusCode != 200) { - display.clearDisplay(); - display.setCursor(0, 0); - display.printf("http non-ok: %d\n", statusCode); - display.display(); - for (;;); - return; - } - - display.clearDisplay(); - display.setCursor(0, 0); - display.print(client.getString()); - display.display(); + String departuresRaw = fetchDepartures(); + deserializeJson(departures, departuresRaw); state = SHOWING_DEPARTURES; - delay(FRAME_DELAY); + frame = 0; return; } @@ -125,13 +130,48 @@ void loop() { return; } + /* if (buttonPushed) { buttonPushed = false; delay(FRAME_DELAY); return; } + */ + + // Marquee effect for direction strings longer than 11 characters + // Neither particularly efficient nor legible + // (This could use some love) + + int availableWidth = 11; + + display.clearDisplay(); + display.setCursor(0, 0); + for (JsonVariant departure : departures["departures"].as()) { + const char *directionStr = departure["direction"].as(); + + char buf[128] = {0}; + const char *dirStart; + + if (strlen(directionStr) <= availableWidth || (strlen(directionStr) + 3 + availableWidth) > 127) { + dirStart = directionStr; + } else { + memcpy(buf, directionStr, strlen(directionStr)); + memcpy(buf + strlen(directionStr), " ", 3); + memcpy(buf + strlen(directionStr) + 3, directionStr, availableWidth); + buf[strlen(directionStr) + 3 + availableWidth] = '\0'; + dirStart = buf + frame % (strlen(directionStr) + 3); + } + + display.printf("%2s %-11.11s %6s\n", + departure["symbol"].as(), + dirStart, + departure["leaving"].as() + ); + } + display.display(); - delay(FRAME_DELAY); + frame++; + delay(500); return; } }