/*
Команды для контролера МПТ ЖКИ
192.168.1.177/str – вывод начальной заставки(+ IP адрес).
192.168.1.177/clr -полное очищение лсд дисплея.
192.168.1.177/mes[1,2,3][сообщение]/ -запись сообщения в внутренний буфер. Номер сообщения.
192.168.1.177/wrt[0,1][0-16][1,2,3] -вывод сообщения на лсд дисплей. Номер строки. Позиция на строке. Номер сохранённого сообщения.
192.168.1.177/cip/192/168/1/187- изменение IP адресса на 192.168.1.187
http://192.168.1.177/wrt003-вывод строки 3 в позицию  0 на строке 0.
http://192.168.1.177/wrt123-вывод строки 3 п позицию 2 на строке 1.
192.168.1.177/Reb – перезагрузка системы.



Структура слова конфигурации: команда cnf
 */
#include <OneWire.h>
#include <EEPROM.h>
#include <SPI.h>
#include <Ethernet2.h>
#include <LiquidCrystal.h>
#include <avr/wdt.h>
OneWire ds(7); // выход считывателя на 7 пин
byte addr[8];// буфер приема
byte ip3=192;
byte ip2=168;
byte ip1=1;
byte ip0=177;
byte conf_adr_ip0=4,
     conf_adr_ip1=3,
     conf_adr_ip2=2,
     conf_adr_ip3=1;
byte conf_enable = 0;
String tm;//последний прочитанный ключ RFID

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};

byte get_len=50;
byte D;
String command_start="str", command_clear="clr",command_setmessage="mes",command_write="wrt",command_reboot="reb",command_test="tst",command_eep="eep",command_changeIP="cip",command_rrf="rrf";
String savecom,contain="NO COMMAND";
String dlin;
String mes1="/41/50/54/43/45/4B";

String mes2="/4d/65/73/73/61/67/65/32";

String mes3="/a0/b2/a1/b4/d9/da";
//String mes_welcome="\x4F\x4F\x4F\x20\x4F\x4F\x4F";
String mes_welcome="/a1/6f/bf/6f/b3/20/ba/20/70/61/b2/6f/bf/65/2e",mes_Reboot="/a8/65/70/65/b7/61/b4/70/79/b7/ba/61",mes_ver="/31/2e/33";
String mes_ip="/31/39/32/2e/31/36/38/2e/31/2e/31/37/37";


// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
String strok1, strok2, strok3,strok4;
char l;
boolean flagEmptyLine = true; // признак строка пустая
char tempChar;
char urnFromRequest[51];  // строка URN из запроса
boolean urnReceived= false; // признак URN принят
unsigned int indUrn;  // адрес в строке URN
const int rs = 9, en = 8, d4 = 3, d5 = 4, d6 = 5, d7 = 6;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  if(EEPROM.read(conf_enable)==0)
{
  ip3=EEPROM.read(conf_adr_ip3);
  ip2=EEPROM.read(conf_adr_ip2);
  ip1=EEPROM.read(conf_adr_ip1);
  ip0=EEPROM.read(conf_adr_ip0);
}

IPAddress ip(ip3, ip2, ip1, ip0);
  // Open serial communications and wait for port to open:
  wdt_enable(WDTO_8S);
  lcd.begin(20, 4);
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  //Serial.print("server is at ");
  //Serial.println(Ethernet.localIP());
  welcome();
}
//функция перезагрузки Контролера 
void(* resetFunc) (void) = 0;
  
  
  unsigned int hexToDec(String hexString) 
  {
  unsigned int decValue = 0;
  int nextInt;
  
  for(int i = 0; i < hexString.length(); i++) {
    
 nextInt = int(hexString.charAt(i));
    if (nextInt >= 48 && nextInt <= 57) nextInt = map(nextInt, 48, 57, 0, 9);
    if (nextInt >= 65 && nextInt <= 70) nextInt = map(nextInt, 65, 70, 10, 15);
    if (nextInt >= 97 && nextInt <= 102) nextInt = map(nextInt, 97, 102, 10, 15);
 nextInt = constrain(nextInt, 0 , 15);
    
 decValue = (decValue * 16) + nextInt;
  }
  
  return decValue;
}


//процедура преобразования кодов символов ЖК индикатора 
//входной параметр строка с разделителями "/"
//на выходе строка без разделителей
String convert_mes(String mes)
{
  char h;
  String varend;
  String readString;
        for(int i=1; i<mes.length();i=i+3)
        {
      char c =mes[i];
      readString+=c;
      c =mes[i+1];
      readString+=c;
    h=hexToDec(readString);
    varend+=h;
    readString="";
    }
  return varend;
}
//функция вывода строки на дисплей
String lcdout(int row, int col, String mes)
{ 
  String result;
  if(col<21&&row<5)
  {
    lcd.setCursor(col, row);
    lcd.print(convert_mes(mes));
    if(row==0)
    {
      strok1=convert_mes(mes);
    }
    if(row==1)
    {
      strok2=convert_mes(mes);
    }
        if(row==2)
    {
      strok3=convert_mes(mes);
    }
        if(row==3)
    {
      strok4=convert_mes(mes);
    }
    result="OK";
  }
  else
  {
    result="Format Error";
  }
 return result;
}

String tmpl(String content)
{
  String txt="", ppp="", ex_ip="192.168.1.177";
    ppp+= "<!DOCTYPE HTML><html><head><title>ARTONIT MPT</title></head>";
    ppp+= "<h1>ARTONIT MPT</h1>";
    ppp+= "<h4>Command:</h4>";
    ppp+= ex_ip + "/str<br>";// – вывод заставки(+ IP адрес).<br>";
    ppp+= ex_ip + "/clr";// - очищение лсд дисплея.<br>";
    //ppp+= ex_ip + "/mes[1,2,3][mes]/00<br>";// -запись сообщения в буфер.";
    //ppp = ppp + "Номер сообщения.<br>";
    //ppp = ppp + ex_ip + "/wrt[0,1][0-16][1,2,3]";// -вывод сообщения на дисплей [Номер строки][Позиция на строке][Номер сообщения].<br>";
    //ppp = ppp + ex_ip + "/cip/192/168/1/187";//- изменение IP адресса на 192.168.1.187.<br>";
    //ppp = ppp + ex_ip + "/wrt003";//-вывод строки 3 в позицию  0 на строке 0.<br>";
    //ppp = ppp + ex_ip + "/wrt123";//-вывод строки 3 п позицию 2 на строке 1.<br>";
    //ppp = ppp + ex_ip + "/Reb";// – перезагрузк.<br>";
    ppp+= content;
    ppp+= "</html>";
    txt =  ppp;
  return txt;

}
//функция вывода сообщения приветствия. Сообщение выводится при старте.
void welcome()
{  
  lcdout(0,0,mes_welcome);
  lcdout(3,15,mes_ver);
  lcd.setCursor(0,3);
  lcd.print(ip3);
  lcd.print('.');
  lcd.print(ip2);
  lcd.print('.');
  lcd.print(ip1);
  lcd.print('.');
  lcd.print(ip0);
}

//функция присвоения значений переменным mes.
void seveword(char N)
{
  dlin="";
  for(int i=4;i<get_len-20;i++)
  {
      String readstring;
      char c =urnFromRequest[i];
      readstring+=c;
      c =urnFromRequest[i+1];
      readstring+=c;
    if(readstring=="00"){
      break;
    }
            dlin=dlin+urnFromRequest[i];
            readstring="";
  }
  D=dlin.length()-1;
  switch(N)
  {
    // в глобальной переменной urnFromRequest содержатся get_len символов из GET запроса
    //далее надо выбрать строку для сохранение в mes. Она начинатся с символа 4 и завершается либо 00, либо окончанием строки urnFromRequest
  case '1': mes1="";mes1=dlin;break;
  case '2': mes2="";mes2=dlin;break;
  case '3': mes3="";mes3=dlin;break;
  }
}

//вывода значения указаной переменной на сайт.
String strout(char n)
{
  String webdisp="";
  switch(n)
  {
    case '1': webdisp=mes1;break;
    case '2': webdisp=mes2;break;
    case '3': webdisp=mes3;break;
  }
  return webdisp;
}


//Процедура извлечения символов из строки mes с позиции point до разделителя sep
  String parsDEC (String mes, char sep, byte point)
  {
    String res="";
    for(int i=point;i<mes.length();i++)
    {
      if(mes[i]==sep)
         {
          break;
         }
      else
        {
        res+=mes[i];
        }
      }
      return res;
  }
String microlan(void)
{
    tm="";
  String touchmem ="";
  if(ds.reset()){ // если обнаружено устройттво
    ds.write(0x33); // отправляем команду "считать ROM"
    delay(20); // на всякий случай ждем
    for(int i=0;i<8;i++)
    {
      addr[i] = ds.read(); // считываем
      touchmem+=addr[i],HEX;
      touchmem+='/';
    }
   }
   return touchmem;
}


void loop() {
  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    // an http request ends with a blank line
    flagEmptyLine = true;
    urnReceived = false;
    indUrn=0xffff;
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        tempChar = client.read();

        // прием URN
        if( urnReceived == false ) {
          
          if( indUrn == 0xffff ) {
            // пропуск метода
            if( tempChar == '/' ) indUrn=0;  
          }
          else {
            // запись строки
            if( tempChar == ' ' ) {
              // URN закончен
                urnFromRequest[indUrn]=0;
                urnReceived = true;              
            }
            else {
              // загрузка символа URN в строку
              urnFromRequest[indUrn] = tempChar;
              indUrn++;
              if( indUrn > get_len-1 ) {
                // переполнение
                urnFromRequest[get_len]=0;
                urnReceived = true;
              }
            }            
          }          
        }
 
         if (tempChar == '\n' && flagEmptyLine) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          //client.println("Refresh: 10");  // refresh the page automatically every 5 sec
          client.println();
          
          // output the value of each analog input pin
          //lcd.setCursor(0, 1);
          if(strcmp(urnFromRequest, "favicon.ico")==0){for(int i=0;i<51;i++){urnFromRequest[i]='0';}}
  savecom="";
  //выделяем команду из GET запроса
  for(int i=0;i<3;i++)
  {
    savecom=savecom+urnFromRequest[i];
  }
  //Обработка принятых команд.
  
  //Обработка команды установки сообщения в буфер
  if(savecom==command_setmessage)//
  {
   seveword(urnFromRequest[3]);
   contain="mes seve ";
  }
  
  if(savecom==command_start)//Обработка команды старт контролера
  {
   welcome();
   contain="start";
  }

  if(savecom==command_write)//Обработка команды вывода на ЖКИ
  {
    String f;
    f=strout(urnFromRequest[5]);
    int a=0,b=0;
    a=int(urnFromRequest[3])-'0';
    b=int(urnFromRequest[4])-'0';
    lcdout(a,b,f);
    contain="set mes ok";
  }

  if(savecom==command_clear)//Обработка команды очистки экрана 
  {
  lcd.clear(); 
  strok2="";
  strok1="";
  contain="clear";
  }
    if(savecom==command_test)//Обработка команды тест
  {
    lcdout(0,0,command_test);
    int i=0;
    while(i<1000)
    { 
      lcdout(0,0,command_test);
      i++;
      delay(500);
    }
  }
  
  if(savecom==command_changeIP)
  {
    String ips0,ips1,ips2,ips3;
    ips3=parsDEC(urnFromRequest,'/',4);
    ips2=parsDEC(urnFromRequest,'/',4+ips3.length()+1);
    ips1=parsDEC(urnFromRequest,'/',4+ips3.length()+ips2.length()+2);
    ips0=parsDEC(urnFromRequest,'/',4+ips3.length()+ips2.length()+ips1.length()+3);
    if(ips3.toInt( )>0 and ips3.toInt( )<255 
      and ips2.toInt( )>0 and ips2.toInt( )<255
      and ips1.toInt( )>0 and ips1.toInt( )<255
      and ips0.toInt( )>0 and ips0.toInt( )<255)
      {
        EEPROM.write(conf_adr_ip3,ips3.toInt( ));
        EEPROM.write(conf_adr_ip2,ips2.toInt( ));
        EEPROM.write(conf_adr_ip1,ips1.toInt( ));
        EEPROM.write(conf_adr_ip0,ips0.toInt( ));
        EEPROM.write(conf_enable,0);
        client.stop();
        resetFunc(); 
      }
  }


  
  if(savecom==command_reboot)//Обработка команды перезапуска контролера 
{
  lcd.clear(); 
  lcdout(0,0,mes_Reboot);
  client.println("Rebooting!!!!");
  delay(2000);
  client.stop();
  resetFunc(); 
}



if(savecom==command_rrf)
{
  contain = microlan();
  /*lcd.setCursor(0,2); // Вывод номера карты на ЖКИ для отладки
  for(int i=0;i<8;i++)
  {
  lcd.print(addr[i],HEX);
  lcd.print('/');
  }
  */
}
 savecom="";

client.println(tmpl(contain));
          break;
        }
        if (tempChar == '\n') {
          // новая строка
          flagEmptyLine = true;
        } 
        else if (tempChar != '\r') {
          // в строке хотя бы один символ
          flagEmptyLine = false;
        }
      }
      
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
  wdt_reset();
}
