auto switch done, calendar & weather nearly done #16

pull/1/head
Thomas Ballmann 4 years ago
parent 0f29a82542
commit 332f3a7d6c

@ -16,6 +16,6 @@ struct datetime_struct : tm
extern RTC_DATA_ATTR struct datetime_struct now; extern RTC_DATA_ATTR struct datetime_struct now;
void setupDateTime(); bool setupDateTime();
#endif #endif

File diff suppressed because it is too large Load Diff

@ -1,7 +1,14 @@
#ifndef PLAYLIST_H #ifndef PLAYLIST_H
#define PLAYLIST_H #define PLAYLIST_H
#include <WString.h>
void setupPlaylist(); void setupPlaylist();
void loopPlaylist(); void loopPlaylist();
void PlaylistNextFace();
String PlaylistGetCurrentFace();
int32_t PlaylistGetRemainingTimeMs();
void PlaylistResetTimer();
#endif #endif

@ -0,0 +1,8 @@
#ifndef TOOLS_H
#define TOOLS_H
#define EVERY_N_SECONDS(t) for (static uint16_t _lasttime; \
(uint16_t)((uint16_t)millis() - _lasttime) >= (t * 1000); \
_lasttime += (t * 1000))
#endif

@ -1,10 +1,11 @@
#include "app.h" #include "app.h"
#include "SPIFFS.h" #include "SPIFFS.h"
#include "ESPAsyncWebServer.h" #include "ESPAsyncWebServer.h"
#include "AsyncJson.h" //#include "AsyncJson.h"
#include "ArduinoJson.h" #include "ArduinoJson.h"
#include "settings.h" #include "settings.h"
#include "device.h" #include "device.h"
#include "playlist.h"
AsyncWebServer server(80); AsyncWebServer server(80);
@ -56,7 +57,10 @@ void setupApp()
doc["device"]["heap"] = ESP.getFreeHeap(); doc["device"]["heap"] = ESP.getFreeHeap();
doc["device"]["bootCycle"] = deviceGetBootCount(); doc["device"]["bootCycle"] = deviceGetBootCount();
doc["device"]["screen"]["width"] = 640; doc["device"]["screen"]["width"] = 640;
doc["device"]["height"]["screen"] = 384; doc["device"]["screen"]["height"] = 384;
doc["playlist"]["current"] = PlaylistGetCurrentFace();
doc["playlist"]["remaining"] = PlaylistGetRemainingTimeMs() / 1000;
JsonArray capability = doc.createNestedArray("capability"); JsonArray capability = doc.createNestedArray("capability");
capability.add("png"); capability.add("png");

@ -28,13 +28,13 @@ int getNumberOfDays(int month, int year)
return 30; return 30;
} }
void setupDateTime() bool setupDateTime()
{ {
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
if (!getLocalTime(&now)) if (!getLocalTime(&now))
{ {
Serial.println("Failed to obtain time"); Serial.println("Failed to obtain time");
return; return false;
} }
Serial.println(&now, "%A, %B %d %Y %H:%M:%S"); Serial.println(&now, "%A, %B %d %Y %H:%M:%S");
@ -48,4 +48,6 @@ void setupDateTime()
uint16_t y = (now.tm_year + 1900) - a; uint16_t y = (now.tm_year + 1900) - a;
uint16_t m = now.month_num + (12 * a) - 2; uint16_t m = now.month_num + (12 * a) - 2;
now.day_offset = (((1 + y + (y / 4) - (y / 100) + (y / 400) + ((31 * m) / 12)) % 7) + 7) % 7; now.day_offset = (((1 + y + (y / 4) - (y / 100) + (y / 400) + ((31 * m) / 12)) % 7) + 7) % 7;
return true;
} }

@ -3,16 +3,19 @@
#include "datetime.h" #include "datetime.h"
#include "SPIFFS.h" #include "SPIFFS.h"
#include "pngle.h" #include "pngle.h"
#include "tools.h"
#include <Fonts/FreeMono12pt7b.h> // weekday - month year #include <Fonts/FreeMono12pt7b.h> // weekday - month year
#include <Fonts/FreeSansBold24pt7b.h> // current day #include <Fonts/FreeSansBold24pt7b.h> // current day
void downloadRandomePicture();
void display_calender(); void display_calender();
void display_picture(); void display_picture();
void display_time(); void display_time();
void on_draw2(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]); void on_draw2(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]);
using std::uint8_t; using std::uint8_t;
// TODO use dynamic display width
static constexpr int MAX_WIDTH = 640 - 250; static constexpr int MAX_WIDTH = 640 - 250;
static constexpr int MAX_HEIGHT = 384; static constexpr int MAX_HEIGHT = 384;
static int16_t curRowDelta[MAX_WIDTH + 1]; static int16_t curRowDelta[MAX_WIDTH + 1];
@ -20,9 +23,15 @@ static int16_t nextRowDelta[MAX_WIDTH + 1];
void setupFaceCalendar() void setupFaceCalendar()
{ {
Serial.println("setupFaceWeather"); }
void loopFaceCalendar()
{
EVERY_N_SECONDS(300)
{
Serial.println("TODO download new image");
}
setupDateTime();
display.setRotation(0); display.setRotation(0);
display.setFullWindow(); display.setFullWindow();
@ -30,24 +39,18 @@ void setupFaceCalendar()
display.fillScreen(GxEPD_WHITE); display.fillScreen(GxEPD_WHITE);
// draw... // draw...
//display_time();
display_picture(); display_picture();
display_calender(); display_calender();
Serial.println("displayFlush"); Serial.println("displayFlush");
display.nextPage(); display.nextPage();
}
// https://raw.githubusercontent.com/rgujju/paperdink/master/Images/full.jpg void downloadRandomePicture()
// https://github.com/rgujju/paperdink/blob/master/Software/paperd.ink/GUI.cpp {
// https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=640&h=200&fm=png&fit=crop // https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=640&h=200&fm=png&fit=crop
// https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=390&h=384&fm=png&fit=crop&colorquant=2 // https://images.unsplash.com/photo-1580886349729-1bd109928600?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjExMDM0OH0&w=390&h=384&fm=png&fit=crop&colorquant=2
// final filter: &w=390&h=384&fm=png&fit=crop&duotone=000000,FFFFFF // final filter: &w=390&h=384&fm=png&fit=crop&duotone=000000,FFFFFF
// display_weather
}
void loopFaceCalendar()
{
} }
void display_calender() void display_calender()
@ -126,7 +129,6 @@ void display_picture()
pngle_t *pngle = pngle_new(); pngle_t *pngle = pngle_new();
pngle_set_draw_callback(pngle, on_draw2); pngle_set_draw_callback(pngle, on_draw2);
//File file = SPIFFS.open("/blackPNG.png", "r");
File file = SPIFFS.open("/calendarPhoto.png", "r"); File file = SPIFFS.open("/calendarPhoto.png", "r");
if (!file) if (!file)
{ {
@ -151,14 +153,13 @@ void display_picture()
} }
/** /**
* Floyd-Steinberg-Algorithmus * render picture
*/ */
void on_draw2(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4]) void on_draw2(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint8_t rgba[4])
{ {
uint8_t r = rgba[0]; // 0 - 255 uint8_t r = rgba[0]; // 0 - 255
uint8_t g = rgba[1]; // 0 - 255 uint8_t g = rgba[1]; // 0 - 255
uint8_t b = rgba[2]; // 0 - 255 uint8_t b = rgba[2]; // 0 - 255
//uint8_t a = rgba[3]; // 0: fully transparent, 255: fully opaque
int16_t gray = round(r * 0.3 + g * 0.59 + b * 0.11); int16_t gray = round(r * 0.3 + g * 0.59 + b * 0.11);
int16_t blackOrWhite; int16_t blackOrWhite;
@ -181,7 +182,9 @@ void on_draw2(pngle_t *pngle, uint32_t x, uint32_t y, uint32_t w, uint32_t h, ui
int err = oldPixel - newPixel; int err = oldPixel - newPixel;
if (x > 0) if (x > 0)
{
nextRowDelta[x - 1] += err * 3 / 16; nextRowDelta[x - 1] += err * 3 / 16;
}
nextRowDelta[x] += err * 5 / 16; nextRowDelta[x] += err * 5 / 16;
nextRowDelta[x + 1] += err * 1 / 16; nextRowDelta[x + 1] += err * 1 / 16;
curRowDelta[x + 1] += err * 7 / 16; curRowDelta[x + 1] += err * 7 / 16;

@ -1,16 +1,107 @@
#include "faceWeather.h"
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <HTTPClient.h> #include <HTTPClient.h>
#include "faceWeather.h"
#include "faceWeatherIcons.h"
#include "display.h"
#include <Fonts/FreeSansBold24pt7b.h> // current day
// TODO use theme color
void display_current();
void display_forecast();
void setupFaceWeather() void setupFaceWeather()
{ {
// https://github.com/andrei7c4/weatherdisplay
} }
void loopFaceWeather() void loopFaceWeather()
{ {
display.setRotation(0);
display.setFullWindow();
display.firstPage();
display.fillScreen(GxEPD_BLACK);
display.setTextColor(GxEPD_WHITE);
display.setTextSize(1);
display_current();
display_forecast();
display.nextPage();
}
void display_current()
{
// temperature
display.setFont(&FreeSansBold24pt7b);
display.setTextSize(2);
display.setCursor(50, 120);
display.println("");
// icon
const uint *icon = getIconById("02n", 192); // 192
if (icon)
{
display.drawBitmap(272, 30, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
}
// text
display.setTextSize(1);
display.setCursor(400, 300);
//display.println("Ein paar Wolken");
// high
display.setTextSize(1);
display.setCursor(500, 30);
display.println("");
// low
display.setCursor(500, 60);
display.println("-3°");
}
void display_forecast()
{
const uint *icon;
// line forecast
//display.drawLine(0, 250, 640, 250, GxEPD_WHITE);
display.drawRect(0, 250, 640, 2, GxEPD_WHITE);
display.drawLine(210, 250, 210, 384, GxEPD_WHITE);
display.drawLine(420, 250, 420, 384, GxEPD_WHITE);
// 210 per block
// day +1
icon = getIconById("03d", 96);
if (icon)
{
display.drawBitmap(0 +57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
}
// day +2
icon = getIconById("09d", 96);
if (icon)
{
display.drawBitmap(210 +57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
}
// day +3
icon = getIconById("13d", 96);
if (icon)
{
display.drawBitmap(410 +57, 260, (uint8_t *)icon + 4, icon[0], icon[1], GxEPD_WHITE);
}
} }

File diff suppressed because it is too large Load Diff

@ -3,35 +3,91 @@
#include "faceWeather.h" #include "faceWeather.h"
#include "faceCalendar.h" #include "faceCalendar.h"
#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
typedef void (*Face)();
typedef Face FaceList[];
typedef struct
{
Face face;
String name;
} FaceAndName;
typedef FaceAndName FaceAndNameList[];
// List of faces to cycle through
FaceAndNameList faces = {
{loopFaceWeather, "Weather"},
{loopFaceCalendar, "Calendar"},
};
const uint8_t faceCount = ARRAY_SIZE(faces);
unsigned long lastSwitch = 0; unsigned long lastSwitch = 0;
int64_t timer; int32_t timer;
uint8_t currentFaceIndex = 0;
//bool autoplayEnabled = false;
void setupPlaylist() void setupPlaylist()
{ {
Serial.println("setupPlaylist..."); Serial.println("setupPlaylist...");
lastSwitch = millis();
// load timer
timer = NVS.getInt("playlist.timer") * 1000; timer = NVS.getInt("playlist.timer") * 1000;
if (timer < 30000) if (timer < 30000)
{ {
timer = 30000; timer = 30000;
} }
setupFaceWeather();
// setup faces
//setupFaceWeather();
setupFaceCalendar(); setupFaceCalendar();
}
//Serial.print(" Timeout is: ");
//Serial.print(timer);
//Serial.println("");
// force instant update
lastSwitch = millis() - timer;
}
void loopPlaylist() void loopPlaylist()
{ {
// return millis() - bootTime >= 60000; if (PlaylistGetRemainingTimeMs() <= 0) // && autoplayEnabled
if (millis() - lastSwitch >= timer)
{ {
lastSwitch = millis(); PlaylistResetTimer();
Serial.println("switch face"); PlaylistNextFace();
// TODO Serial.println("switch face: " + faces[currentFaceIndex].name);
faces[currentFaceIndex].face();
} }
}
void PlaylistNextFace()
{
currentFaceIndex++;
// wrap around at the ends
if (currentFaceIndex < 0)
{
currentFaceIndex = faceCount - 1;
}
if (currentFaceIndex >= faceCount)
{
currentFaceIndex = 0;
}
}
String PlaylistGetCurrentFace()
{
return faces[currentFaceIndex].name;
}
int32_t PlaylistGetRemainingTimeMs()
{
return timer - (millis() - lastSwitch);
}
void PlaylistResetTimer()
{
lastSwitch = millis();
} }
Loading…
Cancel
Save