|
|
|
#include "screen.h"
|
|
|
|
|
|
|
|
void Screen::next() { Serial.println("unhandled next"); }
|
|
|
|
void Screen::previous() { Serial.println("unhandled previous"); }
|
|
|
|
uint8_t Screen::select() { Serial.println("unhandled select"); }
|
|
|
|
|
|
|
|
SelectionList::SelectionList() {}
|
|
|
|
|
|
|
|
SelectionList::SelectionList(const char* title, uint8_t start_pos, const char* string_list) {}
|
|
|
|
|
|
|
|
void SelectionList::draw() {
|
|
|
|
uint8_t item_x_offset = 15;
|
|
|
|
uint8_t header_height = 12;
|
|
|
|
uint8_t item_height = 12;
|
|
|
|
uint8_t num_active_item = current_pos - top_item;
|
|
|
|
|
|
|
|
u8g2.clearBuffer();
|
|
|
|
|
|
|
|
/* draw Title */
|
|
|
|
u8g2.setFont(u8g2_font_guildenstern_nbp_tr);
|
|
|
|
u8g2.drawUTF8(2,header_height-2,title);
|
|
|
|
u8g2.drawLine(0,header_height,u8g2.getDisplayWidth(),header_height);
|
|
|
|
|
|
|
|
/* draw menu items */
|
|
|
|
u8g2.setFont(u8g2_font_8x13B_tf);
|
|
|
|
int length = std::min(visible, (uint8_t)string_list.size());
|
|
|
|
for (int i=0; i<length; i++) {
|
|
|
|
u8g2.drawUTF8(item_x_offset,header_height+2+(i+1)*item_height,string_list[top_item+i].c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
u8g2.drawFrame(0,header_height+1+num_active_item*item_height,u8g2.getDisplayWidth(),item_height+2 );
|
|
|
|
u8g2.sendBuffer(); // transfer internal memory to the display
|
|
|
|
}
|
|
|
|
|
|
|
|
void SelectionList::next() {
|
|
|
|
if (current_pos < string_list.size()-1) current_pos++;
|
|
|
|
int length = std::min(visible, (uint8_t)string_list.size());
|
|
|
|
if (current_pos > top_item+length-1) top_item++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SelectionList::previous() {
|
|
|
|
if (current_pos > 0 ) current_pos--;
|
|
|
|
if (current_pos < top_item) top_item--;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t SelectionList::select() {
|
|
|
|
switch (current_pos) {
|
|
|
|
// case 0:
|
|
|
|
// break;
|
|
|
|
default:
|
|
|
|
Serial.println("unknown entry selected");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
menuChange = eMainScreen;
|
|
|
|
return current_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
MainMenu::MainMenu() {
|
|
|
|
title = "Main Menu";
|
|
|
|
string_list = {
|
|
|
|
"PLAY",
|
|
|
|
"Radio Stations",
|
|
|
|
"AlarmClock",
|
|
|
|
"Toggle Light",
|
|
|
|
"Wohnzimmer L",
|
|
|
|
"SLEEP",
|
|
|
|
"\xAB Return"};
|
|
|
|
if (mp3.playing) {
|
|
|
|
string_list[0] = "STOP";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t MainMenu::select() {
|
|
|
|
switch (current_pos) {
|
|
|
|
case 0:
|
|
|
|
if (mp3.playing) {
|
|
|
|
mp3.stop();
|
|
|
|
led.changeAnimation(255, 0);
|
|
|
|
} else {
|
|
|
|
mp3.start();
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
menuChange = eStationMenu;
|
|
|
|
return current_pos;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
menuChange = eAlarmClockScreen;
|
|
|
|
return current_pos;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (!led.isOn()) led.changeAnimation(3, 0);
|
|
|
|
else led.changeAnimation(255, 0);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
menuChange = eLightScreen;
|
|
|
|
return current_pos;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
menuChange = eSuspendScreen;
|
|
|
|
return current_pos;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
menuChange = eMainScreen;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Serial.println("unknown entry selected");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
menuChange = eMainScreen;
|
|
|
|
return current_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
StationMenu::StationMenu() {
|
|
|
|
title = "Radio Stations";
|
|
|
|
string_list = {
|
|
|
|
"80s Planet",
|
|
|
|
"Left Coast 70s",
|
|
|
|
"laradio Ska",
|
|
|
|
"French Quarter Jams",
|
|
|
|
"Radio Kol Yavne",
|
|
|
|
"ROCKIN626.COM",
|
|
|
|
"Jive Time Radio",
|
|
|
|
"Live Ireland",
|
|
|
|
"Ye Ol Celtic Pub",
|
|
|
|
"Gone Country - NZCMR",
|
|
|
|
"Radio Essen",
|
|
|
|
"xd0.de MPD",
|
|
|
|
"\xAB Return"};
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t StationMenu::select() {
|
|
|
|
switch (current_pos) {
|
|
|
|
case 0:
|
|
|
|
mp3.start("http://streaming.shoutcast.com/80sPlanet?lang=en-US");
|
|
|
|
strcpy(titleStr, string_list[0].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
mp3.start("http://ice1.somafm.com/seventies-128-mp3");
|
|
|
|
strcpy(titleStr, string_list[1].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
mp3.start("http://streaming.radionomy.com/laradiostrong?lang=de");
|
|
|
|
strcpy(titleStr, string_list[2].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
mp3.start("http://184.171.163.20:8162/stream");
|
|
|
|
strcpy(titleStr, string_list[3].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
mp3.start("http://212.83.129.92:8028/;?type=http&nocache=683");
|
|
|
|
strcpy(titleStr, string_list[4].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
mp3.start("http://192.99.4.210:3574/stream");
|
|
|
|
strcpy(titleStr, string_list[5].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
mp3.start("http://188.165.192.5:8279/stream?icy=http");
|
|
|
|
strcpy(titleStr, string_list[6].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
mp3.start("http://69.167.190.234:8080/stream");
|
|
|
|
strcpy(titleStr, string_list[7].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
mp3.start("http://192.240.102.133:11790/stream");
|
|
|
|
strcpy(titleStr, string_list[8].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 9:
|
|
|
|
mp3.start("http://192.99.41.102:5044/stream");
|
|
|
|
strcpy(titleStr, string_list[9].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 10:
|
|
|
|
mp3.start("http://radioessen.cast.addradio.de/radioessen/simulcast/high/stream.mp3");
|
|
|
|
strcpy(titleStr, string_list[10].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
mp3.start("http://172.16.75.17:8000/mopidy");
|
|
|
|
strcpy(titleStr, string_list[11].c_str());
|
|
|
|
led.changeAnimation(2, 0);
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
menuChange = eMainMenu;
|
|
|
|
return current_pos;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Serial.println("unknown entry selected");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
menuChange = eMainScreen;
|
|
|
|
return current_pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace { /* anonymous namespace for helper functions */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void WelcomeScreen::draw() {
|
|
|
|
u8g2.clearBuffer(); // clear the internal memory
|
|
|
|
u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font
|
|
|
|
u8g2.drawStr(2,10,"esp32-node by hendrik"); // write something to the internal memory
|
|
|
|
if (iot.configuration.get("WifiConfigured") != "True") {
|
|
|
|
u8g2.drawStr(2,30,"NOT CONFIGURED!");
|
|
|
|
u8g2.drawStr(12,40,"SSID: \"ESP32\"");
|
|
|
|
u8g2.drawStr(12,55,"http://192.168.4.1");
|
|
|
|
} else {
|
|
|
|
u8g2.drawStr(2,30,"Welcome!");
|
|
|
|
u8g2.drawStr(12,40,"WiFi connecting");
|
|
|
|
u8g2.setCursor(80, 40);
|
|
|
|
progress++;
|
|
|
|
for (int i = 0; i<progress; i++) {
|
|
|
|
u8g2.print(".");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
u8g2.drawFrame(0,0,u8g2.getDisplayWidth(),u8g2.getDisplayHeight() );
|
|
|
|
u8g2.sendBuffer(); // transfer internal memory to the display
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainScreen::draw() {
|
|
|
|
u8g2.clearBuffer(); // clear the internal memory
|
|
|
|
|
|
|
|
if(millis() - lastVolumeChange <= 1000) {
|
|
|
|
//u8g2.drawXBMP(0,0, IMG_1872_width, IMG_1872_height, IMG_1872_bits);
|
|
|
|
u8g2.setFont(u8g2_font_inb19_mf);
|
|
|
|
u8g2.drawStr(15, 20, "Volume");
|
|
|
|
|
|
|
|
u8g2.drawRBox(10, 28, 108, 22, 5);
|
|
|
|
u8g2.setDrawColor(0);
|
|
|
|
u8g2.drawBox(14+volume, 31, 100-volume, 16);
|
|
|
|
char volumeStr[6];
|
|
|
|
sprintf(volumeStr, "%3d %%", volume);
|
|
|
|
u8g2.setFont(u8g2_font_profont17_mf);
|
|
|
|
u8g2.setFontMode(1);
|
|
|
|
u8g2.setDrawColor(2);
|
|
|
|
u8g2.drawStr(40, 45, volumeStr);
|
|
|
|
u8g2.setFontMode(0);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
} else {
|
|
|
|
u8g2.setFont(u8g2_font_inb19_mf);
|
|
|
|
u8g2.setFontMode(0);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
u8g2.drawStr(0, 20, timeStr);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font
|
|
|
|
u8g2.drawUTF8(0, 30, weatherStr);
|
|
|
|
|
|
|
|
u8g2.drawUTF8(0,42, statusStr);
|
|
|
|
|
|
|
|
u8g2.setFont(u8g2_font_prospero_bold_nbp_tf); // choose a suitable font
|
|
|
|
|
|
|
|
u8g2_uint_t width = u8g2.getUTF8Width(titleStr); // calculate the pixel width of the text
|
|
|
|
|
|
|
|
if (width > u8g2.getDisplayWidth()) {
|
|
|
|
u8g2_uint_t x = titleStr_offset;
|
|
|
|
do { // repeated drawing of the scrolling text...
|
|
|
|
u8g2.drawUTF8(x, 54, titleStr); // draw the scolling text
|
|
|
|
x += width; // add the pixel width of the scrolling text
|
|
|
|
} while( x < u8g2.getDisplayWidth() ); // draw again until the complete display is filled
|
|
|
|
|
|
|
|
// repeated drawing of the scrolling text...
|
|
|
|
|
|
|
|
titleStr_offset-=4; // scroll by one pixel
|
|
|
|
if ( (u8g2_uint_t)titleStr_offset < (u8g2_uint_t)-width )
|
|
|
|
titleStr_offset = 0; // start over again
|
|
|
|
} else {
|
|
|
|
u8g2.drawUTF8((u8g2.getDisplayWidth()-width)/2, 54, titleStr);
|
|
|
|
}
|
|
|
|
uint32_t buffFill = mp3.getBuffFill();
|
|
|
|
if (buffFill > 0 && buffFill <= 100) {
|
|
|
|
u8g2.drawLine(10,60,10+buffFill,60);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
u8g2.sendBuffer();
|
|
|
|
// bme280.printValues();
|
|
|
|
}
|
|
|
|
|
|
|
|
MainScreen::MainScreen() {
|
|
|
|
volume = mp3.getVolume();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t MainScreen::select() {
|
|
|
|
menuChange = eMainMenu;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainScreen::next() {
|
|
|
|
if (volume < 100) volume++;
|
|
|
|
lastVolumeChange = millis();
|
|
|
|
mp3.setVolume(volume);
|
|
|
|
led.setBrightness((255*volume)/100);
|
|
|
|
Serial.printf("volume: %d\n", volume);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainScreen::previous() {
|
|
|
|
if (volume > 0) volume--;
|
|
|
|
lastVolumeChange = millis();
|
|
|
|
mp3.setVolume(volume);
|
|
|
|
led.setBrightness((255*volume)/100);
|
|
|
|
Serial.printf("volume: %d\n", volume);
|
|
|
|
}
|
|
|
|
|
|
|
|
AlarmClockScreen::AlarmClockScreen() {
|
|
|
|
if (getAlarmTime().tm_year < (2016 - 1900)) {
|
|
|
|
time_t now;
|
|
|
|
time(&now);
|
|
|
|
localtime_r(&now, &alarmTime);
|
|
|
|
} else {
|
|
|
|
alarmTime = getAlarmTime();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AlarmClockScreen::draw() {
|
|
|
|
uint8_t header_height = 12;
|
|
|
|
u8g2.clearBuffer();
|
|
|
|
|
|
|
|
/* draw Title */
|
|
|
|
u8g2.setFont(u8g2_font_guildenstern_nbp_tr);
|
|
|
|
u8g2.drawUTF8(2,header_height-2,title);
|
|
|
|
u8g2.drawLine(0,header_height,u8g2.getDisplayWidth(),header_height);
|
|
|
|
|
|
|
|
char alarmStr[9];
|
|
|
|
strftime(alarmStr, sizeof(alarmStr), "%H:%M", &alarmTime);
|
|
|
|
u8g2.setFont(u8g2_font_inb19_mf);
|
|
|
|
u8g2.drawStr(20, 55, alarmStr);
|
|
|
|
|
|
|
|
u8g2.sendBuffer(); // transfer internal memory to the display
|
|
|
|
}
|
|
|
|
|
|
|
|
void AlarmClockScreen::next() {
|
|
|
|
if (millis() - lastRotary <= 40) alarmTime.tm_min+=20;
|
|
|
|
else if (millis() - lastRotary <= 80) alarmTime.tm_min+=5;
|
|
|
|
else alarmTime.tm_min++;
|
|
|
|
lastRotary = millis();
|
|
|
|
|
|
|
|
if (alarmTime.tm_min >= 60) {
|
|
|
|
alarmTime.tm_hour += alarmTime.tm_min/60;
|
|
|
|
alarmTime.tm_hour %= 24;
|
|
|
|
alarmTime.tm_min %= 60;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AlarmClockScreen::previous() {
|
|
|
|
if (millis() - lastRotary <= 40) alarmTime.tm_min-=20;
|
|
|
|
else if (millis() - lastRotary <= 80) alarmTime.tm_min-=5;
|
|
|
|
else alarmTime.tm_min--;
|
|
|
|
lastRotary = millis();
|
|
|
|
|
|
|
|
if (alarmTime.tm_min < 0) {
|
|
|
|
alarmTime.tm_hour += alarmTime.tm_min/60 -1;
|
|
|
|
if (alarmTime.tm_hour < 0) alarmTime.tm_hour = alarmTime.tm_hour%24 +24;
|
|
|
|
alarmTime.tm_min = alarmTime.tm_min % 60 + 60 ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t AlarmClockScreen::select() {
|
|
|
|
time_t now;
|
|
|
|
time(&now);
|
|
|
|
alarmTime.tm_sec = 0;
|
|
|
|
while(difftime(now, mktime(&alarmTime)) >= 0) alarmTime.tm_mday++;
|
|
|
|
setAlarmTime(alarmTime);
|
|
|
|
menuChange = eMainScreen;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SuspendScreen::draw() {
|
|
|
|
suspend(30);
|
|
|
|
}
|
|
|
|
|
|
|
|
LightScreen::LightScreen() {
|
|
|
|
brightness = 50;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LightScreen::draw() {
|
|
|
|
uint8_t header_height = 12;
|
|
|
|
u8g2.clearBuffer();
|
|
|
|
|
|
|
|
/* draw Title */
|
|
|
|
u8g2.setFont(u8g2_font_inb19_mf);
|
|
|
|
u8g2.drawStr(15, 20, "Brightness");
|
|
|
|
|
|
|
|
u8g2.drawRBox(10, 28, 108, 22, 5);
|
|
|
|
u8g2.setDrawColor(0);
|
|
|
|
uint32_t percent = (uint32_t)brightness*100 / 255;
|
|
|
|
u8g2.drawBox(14+percent, 31, 100-percent, 16);
|
|
|
|
char valueStr[6];
|
|
|
|
sprintf(valueStr, "%3d", brightness);
|
|
|
|
u8g2.setFont(u8g2_font_profont17_mf);
|
|
|
|
u8g2.setFontMode(1);
|
|
|
|
u8g2.setDrawColor(2);
|
|
|
|
u8g2.drawStr(40, 45, valueStr);
|
|
|
|
u8g2.setFontMode(0);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
|
|
|
|
u8g2.sendBuffer(); // transfer internal memory to the display
|
|
|
|
}
|
|
|
|
|
|
|
|
void LightScreen::next() {
|
|
|
|
if (millis() - lastRotary <= 40) brightness+=20;
|
|
|
|
else if (millis() - lastRotary <= 80) brightness+=5;
|
|
|
|
else brightness++;
|
|
|
|
if (brightness > 255) brightness = 255;
|
|
|
|
lastRotary = millis();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LightScreen::previous() {
|
|
|
|
if (millis() - lastRotary <= 40) brightness-=20;
|
|
|
|
else if (millis() - lastRotary <= 80) brightness-=5;
|
|
|
|
else brightness--;
|
|
|
|
if (brightness < 0) brightness = 0;
|
|
|
|
lastRotary = millis();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t LightScreen::select() {
|
|
|
|
String topic = "esp32-node/cmd/" + iot.hostname + "/button";
|
|
|
|
|
|
|
|
StaticJsonBuffer<200> jsonBuffer;
|
|
|
|
JsonObject& root = jsonBuffer.createObject();
|
|
|
|
root["brightness"] = brightness;
|
|
|
|
root["light"] = brightness > 0 ? "ON" : "OFF";
|
|
|
|
|
|
|
|
char publishBuf[root.measureLength()+1];
|
|
|
|
root.printTo(publishBuf, sizeof(publishBuf));
|
|
|
|
iot.mqtt.publish(topic.c_str(), 0, false, publishBuf );
|
|
|
|
|
|
|
|
menuChange = eMainScreen;
|
|
|
|
}
|