#include"Define.h"
#include <GSMMannager.h>
#include <HTTPClient.h>
#include <ArduinoHttpClient.h>
#include<driver/periph_ctrl.h>
#include "SensorOptoSky.h"
#include <SoftwareSerial.h>
#include <Ticker.h>
#include <updatebyme.h>
//#include "MyWebServer.h"
#include "SDmanger.h"
//#include "HttpsOTAUpdate.h"
#include "slave.h"
#include "log.h"

#include <wifidebug.h>

#define LOGGING
//myPort将原来ESP8266对内通讯改为，485对内的通讯
// #define MYPORT_TX 45
// #define MYPORT_RX 46
int hassend = 0;
GSMMannger *gsmmanger;
UpDateClassByme *ProgrameUper;
HttpClient *http;
bool ishttpbusy = false;
SensorOptoSky IS1Sensor;
// SoftwareSerial myPort(MYPORT_RX, MYPORT_TX, false);
// HardwareSerial myPort(1);
// swSer(14, 12, false, 256);
// u_char a[]={0x01,0x04,0x00,0x00,0x00,0x06,0x70,0x08};
u_char ret[17];
u_char windret[17];
Ticker ticker;
slave myslave;
String log_path;
String log_data;


String getnetData()
{
    write_log(log_path,100,"http->get11111");
    int err = http->get("/weather/php/Date.php");
    if (err != 0)
    {
        SerialMon.println(F("Date failed to connect"));
        // delay(10000);
        vTaskDelay(10000);
        return "";
    }
    write_log(log_path,100,"http->responseStatusCode222");
    int status = http->responseStatusCode();
    if (!status)
    {
        vTaskDelay(10000);
        return "";
    }

    //  SerialMon.println(F("Response Headers:"));
    write_log(log_path,100,"http->headerAvailable333");
    int times_try = 0;
    while (http->headerAvailable())
    {

        if(times_try > 100) 
        {
            write_log(log_path,100,"http->headerAvailable failed ...");
            return "-1";
        }
        write_log(log_path,100,"http->readHeaderName");
        String headerName = http->readHeaderName();
        write_log(log_path,100,"http->readHeaderValue");
        String headerValue = http->readHeaderValue();
        write_log(log_path,100,String(times_try)+"http->headerName "+headerName);
        write_log(log_path,100,String(times_try)+"http->headerValue "+headerValue);
        // SerialMon.println("Date:    " + headerName + " : " + headerValue);
        vTaskDelay(100);
        times_try++;
    }
    write_log(log_path,100,"http->isResponseChunked4444");
    if (http->isResponseChunked())
    {
        // SerialMon.println(F("Date The response is chunked"));
    }
    write_log(log_path,100,"http->responseBody555");
    String body = http->responseBody();
    http->stop();
    return body;
}

bool UpdateData(String path, char *str, size_t lenth, String Contenttype = "")
{
  
    http->beginRequest();
    http->post(path);
    if (Contenttype != "")
    {
        http->sendHeader(HTTP_HEADER_CONTENT_TYPE, Contenttype);

        /* code */
    }
   
    http->sendHeader(HTTP_HEADER_CONTENT_LENGTH, lenth);
    http->endRequest();
    int err = http->write((const byte *)str, lenth);
    delay(1000);
    Serial.print("send date size");
    Serial.println(err);

      /*
    for (size_t i = 0; i < lenth; i++)
     {
         Serial.print("0x");
        Serial.print(str[i],HEX);
         Serial.print(" ");
                    if (i%20==0)
                  {
                    Serial.println(" ");
                   
                  }
     }
    */
    // http->write((const byte*)IS1Sensor.UpData, IS1Sensor.SensorInfo.BandNum*2);
    // http->stop();
    Serial.println("hear1");
    if (err == 0)
    {
        http->stop();
        return false;
    }
    int status = http->responseStatusCode();
       Serial.println("hear3");
    if (!status)
    {
        http->stop();
        return false;
    }

    int length = http->contentLength();
       Serial.println("hear4");
    if (length == 0)
    {
        http->stop();
        return false;
    }

    String body = http->responseBody();
    Serial.println("body:"+body);
    if (body != "ok")
    {
        http->stop();
        return false;
    }

    http->stop();
    return true;
}
void ReuploadData(String path, String webpath, String content = "")
{
    vTaskDelay(1);
    Vector<String> files;
    String vec[20]; //每次处理20个
    files.setStorage(vec);
    while (!sdcard::ListDir(path.c_str(), files))
    {
        if (files.size() != 0)
        {
            Serial.println("find " + String(files.size()) + "file");
            for (size_t i = 0; i < files.size(); i++)
            {
                File nowfile = SD_MMC.open(files.at(i).c_str(), "rb");
                size_t size = nowfile.size();
                char *arr = new char[size];
                nowfile.readBytes(arr, size);
                bool flagsucc = UpdateData(webpath, arr, size, content);
                if (!flagsucc)
                {
                    return;
                    /* code */
                }
                delete[] arr;
                sdcard::deleteFolderOrFile(files.at(i).c_str());
                vTaskDelay(1);
                /* code */
            }
        }
        vTaskDelay(1);
    }
    if (files.size() != 0)
    {
        Serial.println("find " + String(files.size()) + "file not enough 20");
        for (size_t i = 0; i < files.size(); i++)
        {
             vTaskDelay(1);
            File nowfile = SD_MMC.open(files.at(i).c_str(), "rb");
            size_t size = nowfile.size();
            char *arr = new char[size];
            nowfile.readBytes(arr, size);
            Serial.println("run here now");
            bool flagsucc = UpdateData(webpath, arr, size, content);
            if (!flagsucc)
            {
                return;
                /* code */
            }

            delete[] arr;
            sdcard::deleteFolderOrFile(files.at(i).c_str());
            /* code */
        }
    }
    vTaskDelay(1);
}
String fenge(String str, String fen, int index)
{
    int weizhi;
    String temps[str.length()];
    int i = 0;
    do
    {
        weizhi = str.indexOf(fen);
        if (weizhi != -1)
        {
            temps[i] = str.substring(0, weizhi);
            str = str.substring(weizhi + fen.length(), str.length());
            i++;
        }
        else
        {
            if (str.length() > 0)
                temps[i] = str;
        }
    } while (weizhi >= 0);

    if (index > i)
        return "-1";
    return temps[index];
}
void Reuploaddata(void *) //重新上传数据
{
    ReuploadData("/down", "/weather/php/SpectralDataUp.php");
    ReuploadData("/up", "/weather/php/SpectralDataUp.php");
    ReuploadData("/other", "/weather/php/WindsensorUp.php", "application/json");
}
void Reuploaddata() //重新上传数据
{
    ReuploadData("/down", "/weather/php/SpectralDataUp.php");
    ReuploadData("/up", "/weather/php/SpectralDataUp.php");
    ReuploadData("/other", "/weather/php/WindsensorUp.php", "application/json");
}

String Datenow="";
void printbytcp(String str)
{
  //tcpserver.SendDataToClinet(str);
  Serial.println(str);
    str=Datenow+"#######"+str;
    int lennn=str.length();
    char *temp = new char[lennn];
    memcpy(temp, str.c_str(),  str.length());
   bool flagsucc = UpdateData("/weather/php/log.php", temp, lennn);
   vTaskDelay(3000);
    delete[] temp;

}


void readmeichaung()
{
/////////////////////////////////now///////////////////////////
    double temprature = myslave.getMLX();
    Serial.println("wendu");
    Serial.println(temprature);
    Serial.println("hello word");
////////////////////////////////now////////////////////////////
    myslave.getWehter();
    memcpy(windret,myslave.ret,17);
    float VV = (windret[3] * 256 + windret[4]) * 1.0 / 100;
    float DD = (windret[5] * 256 + windret[6]) * 1.0 / 10;
    float TT = (windret[7] * 256 + windret[8]) * 1.0 / 100;
    float HH = (windret[9] * 256 + windret[10]) * 1.0 / 100;
    long PP = (windret[13] * 256 + windret[14]) * 256 * 256 + (windret[11] * 256 + windret[12]);
    Serial.println("VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP));
}


String get_GPS(void)
{
    Serial.println("check GPS...");
    gsmmanger->modem->sendAT(GF("+CGNSPWR?"));
    gsmmanger->modem->waitResponse("OK");
    
    Serial.println("Open GPS...");
    gsmmanger->modem->sendAT(GF("+CGNSPWR=1"));
    gsmmanger->modem->waitResponse("OK");

    gsmmanger->modem->sendAT(GF("+CGNSAID=31,1,1,1"));
    gsmmanger->modem->waitResponse("OK");

    Serial.println("get GNSS...");
    gsmmanger->modem->sendAT(GF("+CGNSINF"));
    
    String gpsbac;
    gsmmanger->modem->waitResponse(5000,gpsbac);
    // Serial.println(gps);

    write_log(log_path,10,"gpsbac is " + gpsbac);
    String Date =  gpsbac.substring(18,32);
    write_log(log_path,10,"get gps data is " + Date);
    String  temp = Date.substring(0,4) + "-" + Date.substring(4,6) + "-" +Date.substring(6,8) + " " + Date.substring(8,10) + ":" +Date.substring(10,12) + ":" +Date.substring(12,-1);
    Date = temp;

    write_log(log_path,10,"gps time is" + Date);
   
    if(Date.indexOf(",") != -1) 
    {
        return "-1";
    }
    
    Serial.println(gpsbac);
    write_log(log_path,10,"gpsdate:"+Date);
    return Date;
}
// String get_ti()
// {
//    return gsmmanger->modem->getNetworkTime;
// }
void setup()
{
    Serial2.begin(115200);

    Serial.begin(115200);
    sdcard::init_sdcard();
    sdcard::testwriet();
    sdcard::Mkdir("/up");
    sdcard::Mkdir("/down");
    sdcard::Mkdir("/other");
    sdcard::Mkdir("/gps");
    sdcard::Mkdir("/log");
    beginWIFI();
    // sdcard::mylistDir("/",2);
    {
    }
    // pinMode(21, OUTPUT);
    // digitalWrite(21, HIGH);


    myslave.init(46,45);
    sleep(3);
    readmeichaung();
    //原来的SIM800，改为现在的AIR780E4G模块，使用的是串口2。
    gsmmanger = new GSMMannger(2, 19, 20);

    http = new HttpClient(*gsmmanger->client, "82.156.1.111");
    
    String Date = getnetData();
    Serial.println("date is :"+Date);
    String tem = fenge(Date," ",0);
    log_path = "/log/"+tem+".log";
    log_data = Date+"\r\nSystem starts working.";
    write_log(log_path,10,"");
    write_log(log_path,10,log_data);
    write_log(log_path,10,"AIR780E Init Success.");
 


    gsmmanger->modem->sendAT(GF("+CGPIO=1,11,1"));  //点灯
    gsmmanger->modem->waitResponse("OK");
    
    // while (1)
    // {
    //     Serial.println(gsmmanger->GetDataAndTime());
    //     delay(1000);
    // }
    
    write_log(log_path,10,"GPS Init ....");
    for(int a = 0 ; a<100 ;a++)
    {
        String gpsbac = get_GPS();
        if (gpsbac != "-1")
        {
            Serial.println(gpsbac);
            write_log(log_path,10,"GPS Init Success.");
            break;
        }
        vTaskDelay(1000);
        
    } 
    vTaskDelay(1000);
    //////////////////////////////初始化http模块//////////////////////////////////////////////
    // http = new HttpClient(*gsmmanger->client, "82.156.1.111");
    ProgrameUper = new UpDateClassByme(http);

    IS1Sensor.initSensor();
    String StationID = IS1Sensor.SensorInfo.serialnumber;
    String SensorID = IS1Sensor.SensorInfo.SensorName;


    ProgrameUper->initme(Curentvsion);
    ProgrameUper->StationID=StationID;
    ProgrameUper->CheckAndUpdate();
    write_log(log_path,10,"Http Init Success.");
   // ProgrameUper->DownloadFirmwareForurl("");
    ////////////////////////////上传IS1设备信息//////////////////////////////////////////////

    //////////////////////////////初始化IS1///////////////////////////////////////////////////

    // String Date=getnetData();
    String Upheader = StationID + "##" + SensorID + "##" + String(IS1Sensor.SensorInfo.BandNum) + "##" 
    + String(IS1Sensor.SensorInfo.a1,9) + ":" + String(IS1Sensor.SensorInfo.a2,9) + ":" + String(IS1Sensor.SensorInfo.a3,9) + ":" + String(IS1Sensor.SensorInfo.a4,9)+"##"+ProgrameUper->CurrentVersion;
    http->beginRequest();
    http->post("/weather/php/SensorInfoUp.php");
    http->sendHeader(HTTP_HEADER_CONTENT_LENGTH, Upheader.length());
    http->endRequest();
    http->write((const byte *)Upheader.c_str(), Upheader.length());
    http->stop();
    ticker.attach(60 * 60, Reuploaddata);
    write_log(log_path,10,"IS1 Init Success.");
    ///////////////////////////////////////////////////////////////////////////////////////

    log_data = "System Init Success";
    write_log(log_path,10,log_data);
    // Serial.println(gsmmanger->GetDataAndTime());
}
String lastdate="";
void loop()
{
    String Date;

/////////////////NOW/////////////////////
    // String tem = fenge(Date," ",0);
    // log_path = "/log/"+tem+".txt";
    write_log(log_path,10,"");
    write_log(log_path,10,Date);

    String yuliang = String(myslave.getYuliang());
    delay(1010);
    Serial.println("yuliang "+yuliang);
    write_log(log_path,10,"getYuliang :"+yuliang);

/////////////////NOW/////////////////////
    String yuliangfz = String(myslave.getYuliang()); 
    delay(1010);
    Serial.println("fuzhao " + yuliangfz);
    log_data ="fuzhao :"+yuliangfz;
    write_log(log_path,10,log_data);

////////////////////////////NOW///////////////////////////
    myslave.getWehter();
    memcpy(windret,myslave.ret,17);
    float VV = (windret[3] * 256 + windret[4]) * 1.0 / 100;
    float DD = (windret[5] * 256 + windret[6]) * 1.0 / 10;
    float TT = (windret[7] * 256 + windret[8]) * 1.0 / 100;
    float HH = (windret[9] * 256 + windret[10]) * 1.0 / 100;
    long PP = (windret[13] * 256 + windret[14]) * 256 * 256 + (windret[11] * 256 + windret[12]);
    Serial.println("VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP));
    write_log(log_path,10,"VV:" + String(VV) + "DD:" + String(DD) + "TT:" + String(TT) + "HH:" + String(HH) + "PP:" + String(PP));


////////////////////////////NOW///////////////////////////
    String temprature =String(myslave.getMLX());
    Serial.println("wendu");
    Serial.println(temprature);
    log_data ="wendu :"+temprature;
    write_log(log_path,10,log_data);
 
    ////sim 循环
    
    write_log(log_path,10,"start gsmmanger->loop()");
    gsmmanger->loop();
#ifdef DINBIAO
        String Datenow1=getnetData();
        Datenow =fenge(Datenow1, " ", 0) + "_" + fenge(fenge(Datenow1, " ", 1), ":", 0) + "_" + fenge(fenge(Datenow1, " ", 1), ":", 1) + "_" + fenge(fenge(Datenow1, " ", 1), ":", 2);
        IS1Sensor.PrintFunc=printbytcp;
#endif
    write_log(log_path,10,"start TakeOneJob()");
    IS1Sensor.TakeOneJob(); ////IS1采集一次
    String StationID = IS1Sensor.SensorInfo.serialnumber;
    String SensorID = IS1Sensor.SensorInfo.SensorName;

///////////////获取时间
////////通过GPS获取时间，如果获取失败就通过4G访问网页获取。如果获取成功那就对GPS数据进行分割解析出时间。
    String gpsbac;
    for(int i = 0 ;i < 201 ; i++)
    {
        write_log(log_path,10,"start getnetData()");
        Date = getnetData();  
        if(Date == "-1")
        {
            write_log(log_path,10,"start get_GPS()");
            Date = get_GPS(); 
            if(Date != "-1") 
            {
                if(hassend == 0)
                {
                    gpsbac = StationID+"#"+Date;
                    int lennn = gpsbac.length();
                    char *temp = new char[lennn];
                    memcpy(temp, gpsbac.c_str(),  gpsbac.length());
                    bool flagsucc = UpdateData("/weather/php/StationGPSinfo.php", temp, lennn);

                    if (!flagsucc)
                    {
                    // sdcard::WriteStringToFile(nameoffile, temp, lennn);
                    }
                    else{
                    Serial.println("Finish Put StationGPSinfo Data");
                    }
                    delete[] temp;
                
                }
                if(hassend >= 0)
                {
                    hassend--;
                }
            }

        }
        else
        {
               break;
        }
        if (i==200)
        {
            write_log(log_path,10," get_GPS and getnetData failed,esp_restart");
            esp_restart();
        }
        vTaskDelay(500);
        
    }
    write_log(log_path,10,"Date is : "+Date);
    // delay(15000);
    if (fenge(Date, " ", 0)!=lastdate)
    {
        lastdate=fenge(Date, " ", 0);
        log_path = "/log/"+lastdate+".log";
        myslave.claeryuliang();
        ProgrameUper->CheckAndUpdate();

    }

    /////////*获取相关信息*//////////////////////////
    String datestring=fenge(Date, " ", 0) + "_" + fenge(fenge(Date, " ", 1), ":", 0) + "_" + fenge(fenge(Date, " ", 1), ":", 1) + "_" + fenge(fenge(Date, " ", 1), ":", 2);
    String Upheader = Date + "##" + StationID + "##" + SensorID + "##" + "UP" + "##"+String(IS1Sensor.shutterup)+"##";
    String Upname = "/up/" +datestring+ "_" + StationID + "_" + SensorID + "_" + "UP";
    String Downheader = Date + "##" + StationID + "##" + SensorID + "##" + "DOWN" + "##"+String(IS1Sensor.shutterdown)+"##";
    String Downname = "/down/" + datestring + "_" + StationID + "_" + SensorID + "_" + "DOWN";
    String senderID = Date + "##" + StationID + "##" + SensorID + "##" + String(temprature) + "##"+yuliang+"##"+yuliangfz+"##";
    String othername = "/other/" +datestring + "_" + StationID + "_" + SensorID + "_" + String(temprature);
    // Serial.println(senderID);
    // Serial.println( Upheader);
    // Serial.println(Upheader.length());

    //////////////////////上传up数据//////////////////
    write_log(log_path,10,"put up data");
    size_t lennn = IS1Sensor.SensorInfo.BandNum * 2 + Upheader.length();
    char *temp = new char[IS1Sensor.SensorInfo.BandNum * 2 + Upheader.length()];
    memcpy(temp, Upheader.c_str(), Upheader.length());
    char *str=(char *)IS1Sensor.UpData;
    int lenofis=IS1Sensor.SensorInfo.BandNum * 2 ;
     for (size_t i = 0; i < IS1Sensor.SensorInfo.BandNum * 2; i++)
     {
        //temp[Upheader.length()+i]=str[i];
     }
    memcpy(temp + Upheader.length(), IS1Sensor.UpData,IS1Sensor.SensorInfo.BandNum * 2);
    bool flagsucc = UpdateData("/weather/php/SpectralDataUp.php", temp, lennn);
    vTaskDelay(3000);
    if (!flagsucc)
    {
        sdcard::WriteStringToFile(Upname, temp, lennn);
        log_data ="Up_data upload failed,save to SD.";
        write_log(log_path,10,log_data);
    }
    else
    {
        Serial.println("finish Put Up Data");
        log_data ="finish Put Up Data.";
        write_log(log_path,10,log_data);
    }
    delete[] temp;
    


    //////////////////////上传Down数据//////////////////
    write_log(log_path,10,"put dowm data");
    lennn = IS1Sensor.SensorInfo.BandNum * 2 + Downheader.length();
    temp = new char[lennn];
    memcpy(temp, Downheader.c_str(), Downheader.length());
    str=(char *)IS1Sensor.DownData;
    lenofis=IS1Sensor.SensorInfo.BandNum * 2 ;
    for (size_t i = 0; i < IS1Sensor.SensorInfo.BandNum * 2; i++)
    {
        //  temp[Downheader.length()+i]=str[i];
    }
    memcpy(temp + Downheader.length(), IS1Sensor.DownData,IS1Sensor.SensorInfo.BandNum * 2);
    flagsucc = UpdateData("/weather/php/SpectralDataUp.php", temp, lennn);
    vTaskDelay(3000);

    if (!flagsucc)
    {
        sdcard::WriteStringToFile(Downname, temp, lennn);
        log_data ="Down_data upload failed,save to SD.";
        write_log(log_path,10,log_data);
    }else{
        Serial.println("finish Put Down Data");
        log_data ="finish Put Down Data.";
        write_log(log_path,10,log_data);
    }
    delete[] temp;
    
    //////////////////////上传其他数据//////////////////
    lennn = 12 + senderID.length();
    temp = new char[lennn];
    memcpy(temp, senderID.c_str(),  senderID.length());
    memcpy(temp + senderID.length(), windret + 3, 12);
    flagsucc = UpdateData("/weather/php/WindsensorUp.php", temp, lennn, "application/json");
    vTaskDelay(3000);
    if (!flagsucc)
    {
        sdcard::WriteStringToFile(othername, temp, lennn);
        log_data ="put Other Data failed,save to SD.";
        write_log(log_path,10,log_data);
    }else{
        Serial.println("finish Put Other Data");
        log_data ="finish Put Other Data.";
        write_log(log_path,10,log_data);
    }
    delete[] temp;
    

    //结束并等待一定时间
    // http->stop(); delay(100);return;

    delay(120000);
#ifdef DINBIAO
    abort();
    ESP.restart();
#endif 
    return;
}





