#include <ESP8266WiFi.h>

// ***********************************************
String roller_id = "test"; //  MDM

const char* ssid     = "WiFi";  // 
const char* password = "Password"; // 

const char* host = "10.10.0.150";  // 

// ***********************************************

const int buttonUpPin = 5;
const int buttonDownPin = 2;
const int LimitSwitchPin = 4;
const int motor_pin_1 = 16;
const int motor_pin_2 = 13;
const int motor_pin_3 = 12;
const int motor_pin_4 = 14;

int loglevel=2;
  int step_number;
    int StepDelay = 4;
         int StepDelay2 = 500;
           long LastStepTime; 
            long LastStepTime2;  
              int GlobalStepNumber=0;
              int StepDownLimit=30000;
         
int MaxConnectionProbe=30; //   
int CurrentConnectionProbe=0;
bool NetworkMode=0;
long NetworkReconnectTimer=0;
long NetworkReconnectTimeOut=5000;

bool UpAutoFlag=1;
bool UpAutoTimerFlag=0;
long UpAutoTimer;
long UpAutoTimeOut=15000;


bool DirectionMoving=1;
bool GoMoving=LOW;
bool DeviceStartNow=HIGH;             // the current reading from the input pin
bool buttonUpState;             // the current reading from the input pin
bool buttonDownState;             // the current reading from the input pin
bool lastButtonUpState = HIGH;
bool lastButtonDownState = HIGH;
bool lastLimitSwitchState = HIGH;
bool lastReadingUp = HIGH;
bool lastReadingDown = HIGH;
bool lastReadingLimitSwitch = HIGH;

bool countUpStart = 0; //   
bool countDownStart = 0;
bool countLimitSwitchStart = 0;
bool UpPressedLong = 0;
bool DownPressedLong = 0;
bool ignoreDown = 0;

#define holdTime 2000 //,     

long ButtonUpPressTime; // ,     UP
long ButtonDownPressTime; // ,     Down

long lastDebounceUpTime = 0;  //     UP
long lastDebounceDownTime = 0;  //     DOWN
long lastDebounceLimitSwitchTime = 0; 

long debounceDelay = 50; 

WiFiServer server(80);

void setup() {
    WiFi.mode(WIFI_STA);

  // initialize digital pin's


 pinMode(buttonUpPin, INPUT_PULLUP);
  pinMode(buttonUpPin, INPUT_PULLUP);
   pinMode(buttonDownPin, INPUT_PULLUP);
 
 pinMode(motor_pin_1, OUTPUT);
 pinMode(motor_pin_2, OUTPUT);
 pinMode(motor_pin_3, OUTPUT);
 pinMode(motor_pin_4, OUTPUT);
  digitalWrite(motor_pin_1, 0);
  digitalWrite(motor_pin_2, 0);
  digitalWrite(motor_pin_3, 0);
  digitalWrite(motor_pin_4, 0);

  Serial.begin(57600); 
  
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
    CurrentConnectionProbe++;
    if (CurrentConnectionProbe > MaxConnectionProbe)
    goto OfflineMode;
  }
  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
  Serial.println("Server started");
  NetworkMode=1;
  goto OnlineMode;
OfflineMode:
NetworkMode=0;

  Serial.println("");
  Serial.println("WiFi is NOT connected");  
  Serial.println("Server NOT started");
  Serial.println("Go to Offline Mode");
OnlineMode:
  Serial.println("");
}

void loop() {         // LOOP Start +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

  yield();

  //     :
int ReadingUp = digitalRead(buttonUpPin);
int ReadingDown = digitalRead(buttonDownPin);
int ReadingLimitSwitch = digitalRead(LimitSwitchPin);

//   ,  ,  LimitSwitch  -      .    

if (UpAutoFlag && ReadingLimitSwitch)
{
  UpAutoTimerFlag=1;
  UpAutoTimer=millis();
                if (loglevel > 0)      
              Serial.println("Start Timer Auto Up Command");
}
  UpAutoFlag=0;
//   ,   -  

if (ReadingLimitSwitch && UpAutoTimerFlag)
{
  if((millis()-UpAutoTimer)>UpAutoTimeOut)
  {
      CommandUp();
                  if (loglevel > 0)      
              Serial.println("Up Command by Timer");
      UpAutoTimerFlag=0;
  }
}

 
 //  ++++++    ""
  if (ReadingUp != lastButtonUpState) //   
   lastDebounceUpTime = millis(); //   -  

  if ((millis() - lastDebounceUpTime) > debounceDelay)  //           debounceDelay
{
    if (!UpPressedLong && ReadingUp == LOW && countUpStart >0 && (millis() - ButtonUpPressTime) > long(holdTime)) //  
        {
        ButtonUpPressTime = millis();
        UpPressedLong = 1;
         //    __  __ ,  1 

  if(!NetworkMode)
  {

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  
  }





              if (loglevel > 0)      
              Serial.println("Button up pressed long");
              
              String url = String("/objects/?object=")+roller_id+"&op=m&m=ButtonUpLong&";
              SendToMDM(url);
         // -------------       
        }
    if (ReadingUp != buttonUpState) {  //      
      buttonUpState = ReadingUp;  // =  
      if (buttonUpState == LOW){ //  
        countUpStart = 1;     
        ButtonUpPressTime = millis();   
      }
      if (buttonUpState == HIGH) {
 if (ReadingUp == HIGH && lastReadingUp == LOW && !UpPressedLong) //   ,     

{//    __   __ ,  1   !!

              //  
CommandUp();
              
              if (loglevel > 0)      
              Serial.println("Button up pressed short");
           
           String url = String("/objects/?object=")+roller_id+"&op=m&m=ButtonUp&";
           SendToMDM(url);
}// -------------       
 countUpStart = 0; 
 UpPressedLong = 0;
      }
lastReadingUp = ReadingUp;
  }
}
  lastButtonUpState = ReadingUp; 
// -----    ""

 //  ++++++    ""
  if (ReadingDown != lastButtonDownState) //   
   lastDebounceDownTime = millis(); //   -  

  if ((millis() - lastDebounceDownTime) > debounceDelay)  //           debounceDelay
{
    if (!DownPressedLong && ReadingDown == LOW && countDownStart >0 && (millis() - ButtonDownPressTime) > long(holdTime)) //  
        {
        ButtonDownPressTime = millis();
        DownPressedLong = 1;
         //    __    __ ,  1 

                MotorStop();
                
              if (loglevel > 0)      
              Serial.println("Button Down pressed long");
              
              String url = String("/objects/?object=")+roller_id+"&op=m&m=ButtonDownLong&";
              SendToMDM(url);
         // -------------       
        }
    if (ReadingDown != buttonDownState) {  //      
      buttonDownState = ReadingDown;  // =  
      if (buttonDownState == LOW){ //  
        countDownStart = 1;     
        ButtonDownPressTime = millis();   
      }
      if (buttonDownState == HIGH) {
 if (ReadingDown == HIGH && lastReadingDown == LOW && !DownPressedLong) //   ,     

{//    __   __,  1   !!

//  
CommandDown();
  
              if (loglevel > 0)      
              Serial.println("Button Down pressed short");
           
           String url = String("/objects/?object=")+roller_id+"&op=m&m=ButtonDown&";
           SendToMDM(url);
}// -------------       
 countDownStart = 0; 
 DownPressedLong = 0;
      }
lastReadingDown = ReadingDown;
  }
}
  lastButtonDownState = ReadingDown; 
// -----    ""

//  ++++++   

if (ReadingLimitSwitch==LOW && lastReadingLimitSwitch == HIGH)
{ //  
   
   if (loglevel > 0)      
              Serial.println("Limit Switch to Closed now");
  
  if (GoMoving==1 && DirectionMoving == 1)
  {
  MotorStop();

   if (loglevel > 0)      
              Serial.println("Motor stop by Limit Switch!");
             
             String url = String("/objects/?object=")+roller_id+"&op=m&m=StopByLimitSwitch&";
           SendToMDM(url);

  }
  
lastReadingLimitSwitch = ReadingLimitSwitch;
} 
if (ReadingLimitSwitch==HIGH && lastReadingLimitSwitch == LOW)
{ //  
   if (loglevel > 0)      
              Serial.println("Limit Switch Open");
  
lastReadingLimitSwitch = ReadingLimitSwitch;
}
// -----   

Moving (); //  ( ,   )

//    
if(GoMoving==1 && GlobalStepNumber > StepDownLimit)
{
MotorStop(); //   
   if (loglevel > 0)      
              Serial.println("Stop by limit step");
           String url = String("/objects/?object=")+roller_id+"&op=m&m=StopByDownLimit&";
           SendToMDM(url);

             
}
 if (GoMoving==1){
  
   if (millis() -LastStepTime2 >= StepDelay2)
  { 
    if (loglevel == 1)
   {
    Serial.print(".");
   }
    if (loglevel > 1)
   {
 Serial.println(GlobalStepNumber);
   }
LastStepTime2 = millis();  
  }

 }

//   -  1 
if (DeviceStartNow)
{
   if (loglevel > 0)      
              Serial.println("Device Start Now!");
              
              String url = String("/objects/?object=")+roller_id+"&op=m&m=DeviceStartNow&";
              SendToMDM(url);
if (ReadingLimitSwitch==LOW)
{ //    
   if (loglevel > 0)      
              Serial.println("Limit Switch Closed On Start");
lastReadingLimitSwitch = ReadingLimitSwitch;
}
         

DeviceStartNow=LOW;
}  
  ///####################################### WiFi server section
if(NetworkMode){
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
  
  // Read the first line of the request
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  
  // Match the request
  int val;
  if (req.indexOf("/?log+") != -1){
    loglevel++;
  }
  else if (req.indexOf("/?log-") != -1){
    loglevel--;
  }
    else if (req.indexOf("/?open") != -1){
    CommandUp();
  }
    else if (req.indexOf("/?close") != -1){
    CommandDown();
  }
else if (req.indexOf("/?stop") != -1){
    MotorStop();
       if (loglevel > 0)      
              Serial.println("Stop by web command");
      }
  else if (req.indexOf("/?timer") != -1){
    UpAutoTimerFlag=0;
       if (loglevel > 0)      
              Serial.println("Timer cleared by web command");
    GlobalStepNumber = (StepDownLimit+1);
    
  }
    else if (req.indexOf("/?status") != -1){
    //fg
  }
  else {
    //Serial.println("invalid request");
    client.stop();
    return;
  }
  
  client.flush();

  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\n";
//  s += ledState;
  s += "</html>\n";

  // Send the response to the client
  client.print(s);
  delay(1);
  Serial.println("Client disonnected");
}  
  //###########################################  END WiFi server section
  
}           // ------------------------------------------------- End LOOP


void SendToMDM(String turl){
if(NetworkMode){
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  String url = turl;
  Serial.print("Requesting URL: ");
  Serial.println(url);
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  delay(50);
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  Serial.println();
  Serial.println("closing connection");
  client.stop();
}
}


  void GoStep(int thisStep)
{
 switch (thisStep) {
    case 0:    // 0001
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
    break;
    case 1:    // 0011
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, HIGH);
    break;
    case 2:    //0010
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
    break;
    case 3:    //0110
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, HIGH);
      digitalWrite(motor_pin_4, LOW);
    break;
    case 4:    // 0100
      digitalWrite(motor_pin_1, LOW);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, LOW);
    break;
    case 5:    // 1100
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, HIGH);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, LOW);
    break;
    case 6:    //1000
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, LOW);
    break;
    case 7:    //1001
      digitalWrite(motor_pin_1, HIGH);
      digitalWrite(motor_pin_2, LOW);
      digitalWrite(motor_pin_3, LOW);
      digitalWrite(motor_pin_4, HIGH);
    break;
  }
}


void MotorStop()
{
if (GoMoving)
{
GoMoving=LOW;
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, LOW);
  if (loglevel > 0)      
  Serial.println("Motor stopped");
  Serial.println(GlobalStepNumber);
  
}
}


void CommandUp()
{
if(!GoMoving)
{
GoMoving=HIGH;
DirectionMoving=1;
           String url = String("/objects/?object=")+roller_id+"&op=m&m=GoUpMoving&";
           SendToMDM(url);
}
else
MotorStop();
}




void CommandDown()
{
if(!GoMoving)
{
GoMoving=HIGH;
DirectionMoving=0;
           String url = String("/objects/?object=")+roller_id+"&op=m&m=GoDownMoving&";
           SendToMDM(url);

}
else
MotorStop();
}




void Moving (void)
{
  if (GoMoving==1){
   
if (GlobalStepNumber <0)
GlobalStepNumber=1;
   

  if (millis() -LastStepTime >= StepDelay) 
{
     LastStepTime = millis();
//  
if (DirectionMoving==1){
GoStep(step_number);
  step_number++;
  GlobalStepNumber--;
if (step_number > 7)
{step_number = 0;}
}
//  
if (DirectionMoving==0){

if (step_number == 0)
step_number = 7;
GoStep(step_number);
  step_number--;
  GlobalStepNumber++;
          }
    }
}

}