/*
 * Doorbell Speaker for WEMOS D1 mini with dfplayer
 * by Tilman Liero
 * www.tilman.de
 * 
 * Sources:
 * dfplayer library: https://github.com/DFRobot/DFRobotDFPlayerMini via https://wolles-elektronikkiste.de/dfplayer-mini-ansteuerung-mit-dem-arduino
 * info on how to use dfplayer with WEMOS D1: https://forum.arduino.cc/t/dfplayer-mini-mit-wemos-d1-uno/677980/3
 * WEMOS D1 WiFi setup: https://averagemaker.com/2018/04/how-to-set-up-wifi-on-a-wemos.html
 * ESP8266 web server: https://randomnerdtutorials.com/esp8266-web-server/
 * ESP8266 GET request: https://makesmart.net/esp8266-http-get-request/
 */


#include <DFRobotDFPlayerMini.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

DFRobotDFPlayerMini dfPlayer;
int volume = 22;

const char* ssid     = "SSID";
const char* password = "PASSWORD";

WiFiServer server(80);
String header;

String webhook = "http://www.google.com/";
WiFiClient webClient;
HTTPClient http;

void setup()
{
  // start serial output
  Serial.begin(115200);
  Serial.println();

  Serial.println("Connect dfplayer");
  Serial1.begin(9600); // TX on PIN D3, RX on PIN D4
  dfPlayer.begin(Serial1);
  delay(100);
  dfPlayer.setTimeOut(500); // Set serial communication time out 500ms
  dfPlayer.volume(volume);  // Set volume value (0~30).
  dfPlayer.EQ(DFPLAYER_EQ_NORMAL);
  dfPlayer.outputDevice(DFPLAYER_DEVICE_SD);

  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.hostname("Doorbell");
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected, IP address: ");
  Serial.println(WiFi.localIP());
  WiFi.setAutoReconnect(true);
  WiFi.persistent(true);

  server.begin();
  delay(500);
  dfPlayer.play(2);  // Play the second mp3
  
  Serial.println("Setup completed");
}


void loop() {

  WiFiClient client = server.available();   // Listen for incoming clients
  
  if (client) {
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        //Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type: text/html; charset=utf-8");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /bell/on") >= 0) {
              dfPlayer.play(1);  // play the first mp3
              Serial.println("RING");
            }
            else  if (header.indexOf("GET /play/") >= 0) { // yes, I know this is not RESTful
              String str1 = header;
              str1 = str1.substring(header.indexOf("GET /play/") + 10);
              int fileNo = str1.substring(0, str1.indexOf(" ")).toInt();
              
              Serial.print("Play file ");
              Serial.println(fileNo);
              
              if (fileNo <= 1) {
                dfPlayer.play(1);
              }
              else {
                dfPlayer.play(fileNo);
              }
            }
            else if (header.indexOf("GET /setvolume/") >= 0) {
              String str1 = header;
              str1 = str1.substring(header.indexOf("GET /setvolume/") + 15);
              volume = str1.substring(0, str1.indexOf(" ")).toInt();
              
              if (volume < 0) {
                volume = 0;
              }
              else if (volume > 30) {
                volume = 30;
              }
              
              dfPlayer.volume(volume);
              Serial.print("Volume set to ");
              Serial.println(volume);
            }
            else if (header.indexOf("GET /restart") >= 0) {
              Serial.println("Restarting...");
              ESP.restart();
            }
            else if (header.indexOf("GET /dfreset") >= 0) {
              Serial.println("Reset dfplayer...");
              dfPlayer.reset();
            }
              
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            client.println("<title>Doorbell</title>");
            client.println("<style>html { font-family: sans-serif; display: inline-block; margin: 0px auto; text-align: center; }");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 { background-color: #4CAF50; border: none; color: white; padding: 4px 10px; text-decoration: none; margin: 1px; cursor: pointer;}</style></head>");
            
            client.println("<body><h1>Doorbell</h1>");
            client.println("<p>Volume: <a href=\"/setvolume/" + String(volume-1) + "\"><button class=\"button2\">&minus;</button></a> " + String(volume) + " <a href=\"/setvolume/" + String(volume+1) + "\"><button class=\"button2\">&plus;</button></a></p>");
            client.println("<p><a href=\"/bell/on\"><button class=\"button\">Ring</button></a></p>");
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();

            // call webhook after ringing
            if (header.indexOf("GET /bell/on") >= 0) {
              
              if (http.begin(webClient, webhook)) {
                int httpCode = http.GET();
                
                if (httpCode > 0) {
                  if (httpCode == HTTP_CODE_OK) {
                    String payload = http.getString();
                    //Serial.println(payload);
                  }
                }
                else {
                  Serial.printf("HTTP Error: ", http.errorToString(httpCode).c_str());
                }
                // close connection
                http.end();
              }
              else {
                Serial.println("Could not send HTTP request");
              }
            }
            
            break;
          }
          else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        }
        else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected");
    Serial.println("");
  }
}
