/*
Sonderzeichen für die Darstellung auf dem LCD Display
\40 !
\41 "
\42 #
\43 $
\44 %
\45 &
\50 (
\51 )
\52 *
\53 Plus-Zeichen
\54 Komma
\55 Minus-Zeichen
\56 Punkt
\57 Schrägstrich
\72 Doppelpunkt
\73 Semikolon
\74 <
\75 Gleichheitszeichen
\76 >
\77 ?
\100 @
\134 eckige Klammer links
\136 eckige Klammer rechts
\137 accent circonflexe
\138 Unterstrich
\140 accent grave
\173 geschweifte Klammer links
\174 senkrechter Strich
\175 geschweifte Klammer rechts
\176 Pfeil nach rechts
\177 Pfeil nach links
\260 Minuszeichen
\333 Kastenrahmen
\337 hochgestellter Kastenrahmen(wie Potenz)
\340 gr. alpha
\341 ä
\342 ß
\343 klein epsilon
\344 µ
\350 Wurzelzeichen
\351 hoch minus 1
\353 hoch x
\356 n mit Oberstrich ( spanisch )
\357 ö
\363 Zeichen unendlich
\364 Ohm
\365 ü
\366 gr.Summe
\367 pi ( klein )
\371 u mit strich rechts unten
\375 geteilt durch
\377 alle Leuchtpunkte eingeschaltet
*/
#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <ArduinoJson.h>
#include <LinkedList.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address: "0x3F" or "0x27"
int currentPageDepth = 0;
int currentItemIndex = 0;
char menuConfig[] = "{\"Sensoren\":{\"Lufttemp.\":\"\",\"Wassertemp.\":\"\",\"Luftfeucht.\":\"\",\"EC\":\"\",\"PH\":\"\",\"PAR\":\"\",\"Schlie\342er\":\"\",\"Wasserdruck\":\"\"},\"Aktoren\":{\"Druckventil\":{\"\357ffnen\":{\"Best\341tigen\":\"\",\"Abbrechen\":\"\"},\"Schlie\342en\":{\"Best\341tigen\":\"\",\"Abbrechen\":\"\"}},\"Wasserventil\":{\"\357ffnen\":{\"Best\341tigen\":\"\",\"Abbrechen\":\"\"},\"Schließen\":{\"Best\341tigen\":\"\",\"Abbrechen\":\"\"}}},\"Einstellungen\":{\"Helligkeit\":\"\"}}";
StaticJsonDocument<500> menuJson;
DeserializationError error = deserializeJson(menuJson, menuConfig);
LinkedList<String> pageItems = LinkedList<String>();
LinkedList<String> usedPages = LinkedList<String>();
const byte upButtonPin = 4;
const byte downButtonPin = 5;
const byte rightButtonPin = 6;
const byte leftButtonPin = 7;
boolean button_flag = 0;
unsigned long previousMillis = millis();
void setButtonFlag(){
previousMillis = millis();
button_flag = 1;
}
void resetButtonFlag(){
button_flag = 0;
}
int checkButtonPressed(){
if (digitalRead(rightButtonPin) == LOW && button_flag == 0)
{
setButtonFlag();
return 1;
}
if (digitalRead(leftButtonPin) == LOW && button_flag == 0)
{
setButtonFlag();
return 2;
}
if (digitalRead(downButtonPin) == LOW && button_flag == 0)
{
setButtonFlag();
return 3;
}
if (digitalRead(upButtonPin) == LOW && button_flag == 0)
{
setButtonFlag();
return 4;
}
return 0;
}
void showHeader(String title){
clearHeader();
String header = "| " + title + " |";
uint8_t spaceCount = (20 - title.length() - 4)/2;
String buffer = "";
for(int i = 0; i < spaceCount; i++){
buffer += " ";
}
lcd.setCursor(0, 0);
lcd.print(buffer + header);
}
void updateHeaderPage(){
lcd.setCursor(17,0);
lcd.print(String(currentItemIndex/3+1) + "/" + String(((pageItems.size()-1)/3)+1));
}
void clearLines(){
for(int i = 0; i < 3; i++){
lcd.setCursor(0,i+1);
for(int n = 0; n < 20; n++){
lcd.print(" ");
}
}
}
void clearHeader(){
lcd.setCursor(0,0);
for(int n = 0; n < 20; n++){
lcd.print(" ");
}
}
void showLines(String currentMenuItem){
clearLines();
int currentSet = currentItemIndex/3;
for(int i = 0; i < 3; i++){
lcd.setCursor(0,i+1);
String line = pageItems.get(i+3*(currentSet));
if(line == currentMenuItem && currentMenuItem != ""){
// Serial.println("'" + line + "' selected.");
line = "> " + line;
}
lcd.print(line);
}
}
boolean nextPageExists(){
if(currentPageDepth == 0){
return true;
}
JsonObject obj = menuJson.as<JsonObject>();
for(int i = 0; i < usedPages.size(); i++){
obj = obj[usedPages.get(i)];
}
if(obj[pageItems.get(currentItemIndex)].isNull()){
return false;
}
return true;
}
void nextPage(){
if(nextPageExists()){
String used = pageItems.get(currentItemIndex);
if(used == "Best\341tigen"){
String modul = usedPages.get(currentPageDepth-2);
Serial.println(modul);
//call modul function
// TO DO
prevPage();
return;
}
else if(used == "Abbrechen"){
prevPage();
return;
}
else{
currentPageDepth++;
usedPages.add(used);
//Serial.println("Added " + used + " to usedPages.");
currentItemIndex = 0;
}
}
}
void prevPage(){
currentPageDepth--;
// remove currentPage from used List
usedPages.pop();
if (currentPageDepth < 0){
currentPageDepth = 0;
}
currentItemIndex = 0;
}
boolean nextItemExists(int index){
return pageItems.size() - 1 > index;
}
void nextItem(){
if(nextItemExists(currentItemIndex)){
currentItemIndex++;
}
}
void prevItem(){
currentItemIndex--;
if (currentItemIndex < 0){
currentItemIndex = 0;
}
}
void updatePage(){
if(currentPageDepth == 0){
showMainPage();
return;
}
buildItemList(currentPageDepth);
//Serial.println(currentPageDepth);
showHeader(usedPages.get(currentPageDepth-1));
updateHeaderPage();
showLines(pageItems.get(currentItemIndex));
}
void updateList(){
updateHeaderPage();
showLines(pageItems.get(currentItemIndex));
}
void buildItemList(int pageDepth){
// Clear current List
pageItems.clear();
//Serial.println("Current pageitems cleared.");
// Fillup current List with items
int pageDepthCounter = 0;
JsonObject obj = menuJson.as<JsonObject>();
while(pageDepthCounter != pageDepth){
obj = obj[usedPages.get(pageDepthCounter)];
pageDepthCounter++;
}
for (JsonObject::iterator it=obj.begin(); it!=obj.end(); ++it) {
String item = it->key().c_str();
pageItems.add(item);
//Serial.println("Added " + item + " to list.");
}
}
void showMainPage(){
buildItemList(0);
showHeader("Menu");
updateHeaderPage();
showLines(pageItems.get(currentItemIndex));
}
void setup()
{
Serial.begin(115200);
pinMode(upButtonPin, INPUT_PULLUP);
pinMode(downButtonPin, INPUT_PULLUP);
pinMode(rightButtonPin, INPUT_PULLUP);
pinMode(leftButtonPin, INPUT_PULLUP);
lcd.init();
lcd.clear();
lcd.setCursor(0, 0);
showMainPage();
}
void loop()
{
int button = checkButtonPressed();
if(button == 1){
//Serial.println("Right button pressed.");
nextPage();
updatePage();
}
if(button == 2){
//Serial.println("Left button pressed.");
prevPage();
updatePage();
}
if(button == 3){
//Serial.println("Down button pressed.");
nextItem();
updateList();
}
if(button == 4){
//Serial.println("Up button pressed.");
prevItem();
updateList();
}
// 300ms Entprellung mithilfe eines Button-Flags
if (millis() - previousMillis >= 300 && button_flag)
{
resetButtonFlag();
}
}