#include <WiServer.h>
#include <string.h>
#include <SHT1x.h>
//#include <Wire.h>

#define MAX_STRING_LEN  20
#define dataPin  6
#define clockPin 7
const int pumpePin = 3;
const int motorPin = 4;
const int leftPin = 5;

int temperaturSensorKollektor = 2;
int neigungsSensor = 4;

SHT1x sht1x(dataPin, clockPin);

int azimuth = 0;
int elevation = 0;
int pointer = 0;
boolean at = false;
boolean automatic = true;
boolean left, right, pumpe, motor, leftDir = false;

int motorCounter = 0;
int motorVerzoegerung = 100;

int x;

float temp_c = 0;
float humidity = 0;

float vorlauf = 20;
float ruecklauf = 20;
float deltaTemp = 0;

float elevationSoll,elevationIst,azimuthSoll,azimuthIst,kollektortemperatur,aussentemperatur,akkuspannung = 0;
float minElevation, maxElevation, maxTemperatur, elevationValue, elevationValueAlt = 0;

int eleHundert, eleZehn, eleEiner, eleErgebnis, elevationValueSimuliert = 0;
int eleErgebnisAlt = 0;
boolean eleUp = true;
char eins, zwei, drei;

unsigned long updateTime = 30000;
unsigned long updateTimeGet = 15000;
unsigned long time = 0;

String bufferGet, ergebnis;

char bufferPost[256];

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[]    = {192,168,1,2};   // IP address of WiShield
unsigned char gateway_ip[]  = {192,168,1,1};   // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
char ssid[]                 = {"HOMENET"};   // max 32 bytes
unsigned char security_type = 1;               // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"12345678"};	// max 64 characters

// WEP 128-bit keys
prog_uchar wep_keys[] PROGMEM = { 
	0x73, 0x69, 0x6d, 0x6f, 0x6e, 0x61, 0x6e, 0x64, 0x72, 0x65, 0x73, 0x31, 0x32,	// Key 0
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// Key 1
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	// Key 2
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00	// Key 3
};

#define WIRELESS_MODE_INFRA	1
#define WIRELESS_MODE_ADHOC	2
unsigned char wireless_mode = WIRELESS_MODE_INFRA;
unsigned char ssid_len;
unsigned char security_passphrase_len;

 float temp() {
  temp_c = sht1x.readTemperatureC();
  return temp_c;
 }
 
 float humidityFunc() {
  humidity = sht1x.readHumidity();
  return humidity;
}

void neigung() {
  x = analogRead(neigungsSensor);
  //Serial.println(x);
  int minValue = 330;
  int maxValue = 405;
  int xAng = 0;
  elevationValue = map(x, minValue, maxValue, 0, 90);
  elevationValue = (elevationValue + elevationValueAlt) / 2;
  elevationValueAlt = elevationValue;
  
}


/******************************** Funktion Vorlauf - und Ruecklauftemperatur messen *************************/
float temperatur(int ntc) { 
 double sensorValue = analogRead(ntc);
 double Temp = log(((10240000/sensorValue) - 10000));
 Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp));
 Temp = Temp - 273.15;            // Convert Kelvin to Celcius
 return(Temp);
 }
 /****************************************************************************************************/

void printData(char *data, int len) {
  for (len; len > 0; len--) {
    if (*(data) == '@') {
      at = true;
    }
    if (at) {
      bufferGet += *(data);
    }
    Serial.print(*(data++)); 
  }
  if(at) {
  Serial.print("bufferGet: ");
  Serial.println(bufferGet);
  pointer = bufferGet.indexOf('@');
  pointer = pointer + 1;
  eleHundert = char(bufferGet.charAt(pointer)) - 48;
  pointer = pointer + 1;
  eleZehn = char(bufferGet.charAt(pointer)) - 48;
  pointer = pointer + 1;
  eleEiner = char(bufferGet.charAt(pointer)) - 48;
  
  eleErgebnisAlt = eleErgebnis;
  eleErgebnis = (100*eleHundert) + (10*eleZehn) + eleEiner;
  Serial.println(eleErgebnis);
  }
  at = false;
  bufferGet = "";
  uip_close();
}


// This is our page serving function that generates web pages: 1 = links, 2 = rechts, 3 = auto, 4 = manuell
boolean sendMyPage(char* URL) {
    if (URL[0] == '/' && URL[1] == '1' && URL[2] == '?') {
        left = true;
        right = false;
        automatic = false;
        eleErgebnis = eleErgebnis - 10;
        return true;
    }
    if (URL[0] == '/' && URL[1] == '2' && URL[2] == '?') {
        right = true;
        left = false;
        automatic = false;
        eleErgebnis = eleErgebnis + 10;
        return true;
    }
    if (URL[0] == '/' && URL[1] == '3' && URL[2] == '?') {
        automatic = true;
        return true;
    }
     if (URL[0] == '/' && URL[1] == '4' && URL[2] == '?') {
        pumpe = false;
        automatic = false;
        return true;
    }
     if (URL[0] == '/' && URL[1] == '5' && URL[2] == '?') {
        pumpe = true;
        automatic = false;
        return true;
    }
    // 4 Punpe aus, 5, Pumpe ein
    return false;
}

void feedData() { 
//  float postElevationsoll = 5;
//    int postElevationsoll1 = (postElevationsoll - (int)postElevationsoll) * 100;
//    
//  float postElevationist = 0;
//    int postElevationist1 = (postElevationist - (int)postElevationist) * 100;
    
  float postElevationsoll = eleErgebnis;
    int postElevationsoll1 = (postElevationsoll - (int)postElevationsoll) * 100;
    
  float postElevationist = elevationValue;
    int postElevationist1 = (postElevationist - (int)postElevationist) * 100;
    
  float postKollektortemperatur = temperatur(temperaturSensorKollektor);
    int postKollektortemperatur1 = (postKollektortemperatur - (int)postKollektortemperatur) * 100;
    
  float postAussentemperatur = temp();
    int postAussentemperatur1 = (postAussentemperatur - (int)postAussentemperatur) * 100;
    
  float postAkkuspannung = akkuspannung;
    int postAkkuspannung1 = (postAkkuspannung - (int)postAkkuspannung) * 100;
    
  float postFeuchte = humidityFunc();
    int postFeuchte1 = (postFeuchte - (int)postFeuchte) * 100;

  sprintf(bufferPost, "POST &elevationsoll=%0d.%d&elevationist=%0d.%d&kollektortemperatur=%0d.%d&aussentemperatur=%0d.%d&feuchte=%0d.%d&akkuspannung=%0d.%d& HTTP/1.1", (int)postElevationsoll, postElevationsoll1, (int)postElevationist, postElevationist1, (int)postKollektortemperatur, postKollektortemperatur1, (int)postAussentemperatur, postAussentemperatur1, (int)postFeuchte, postFeuchte1,(int)postAkkuspannung, postAkkuspannung1);

  WiServer.print(bufferPost); 
  Serial.println(bufferPost);
}


void akku() {
  float spannung = analogRead(A1);
  spannung = spannung * 0.0049;
  akkuspannung = spannung * 4;
}

void pumpensteuerung() {
  if (pumpe) {
    digitalWrite(pumpePin, HIGH);
  }
  else {
    digitalWrite(pumpePin, LOW);
  }
}

void abweichung () {
  int eleDifferenz = eleErgebnisAlt - eleErgebnis;
  if (eleDifferenz < 0) {
    eleUp == true;
  }
  else {
    eleUp == false;
  }
  if (eleUp) {
    elevationValueSimuliert = elevationValue - 1;
  }
  else {
    elevationValueSimuliert = elevationValue + 1;
  }
  int abweichungsWert = eleErgebnis - elevationValueSimuliert;
  //Serial.println(abweichungsWert);
  if (abweichungsWert > 1) {
    if (motorCounter > motorVerzoegerung) {
      motor = true;
      leftDir = false;
    }
    motorCounter++;
  }
  else {
    if (abweichungsWert < -1) {
       if (motorCounter > motorVerzoegerung) {
          motor = true;
          leftDir = true;
       }
    motorCounter++;
    }
    else {
      motor = false;
      leftDir = false;
      motorCounter = 0;
    }
  }
} 

void ausrichtung() {            //alle Pins invertiert da Relaiskarte LOW => HIGH
  if (leftDir) {
    digitalWrite(leftPin, LOW);
  }
  else {
    digitalWrite(leftPin, HIGH);
  }
  if (motor) {
    digitalWrite(motorPin, LOW);
  }
  else {
    digitalWrite(motorPin, HIGH);
  }
}


uint8 ip[] = {217,26,52,28};
GETrequest getElevation(ip, 80, "parabol.andres.li", "/elevationschliern.php");
POSTrequest postElevation(ip, 80, "parabol.andres.li\nConnection: close", "/??????.php?", feedData);

void setup() {
//    slaveAddress = HMC6352Address >> 1;
//    Wire.begin();
    WiServer.init(sendMyPage);  
    Serial.begin(57600);
    WiServer.enableVerboseMode(true);
    getElevation.setReturnFunc(printData);
    pinMode(motorPin, OUTPUT);
    pinMode(leftPin, OUTPUT);
    pinMode(pumpePin, OUTPUT);
}

void loop(){
time = millis();

if (automatic) {
  if (time > updateTimeGet) {    
    updateTimeGet = time +  (15000);
    getElevation.submit();    
 }

  if (time > updateTime) {    
    updateTime = time +  (30000);
    postElevation.submit();
 }
 akku();
 pumpensteuerung();
 neigung();
 abweichung();
 ausrichtung();
}

if (!automatic) {
  if (time > updateTime) {    
    updateTime = time +  (30000);
    postElevation.submit();
 }
 akku();
 pumpensteuerung();
 neigung();
 abweichung();
 ausrichtung();
}

 WiServer.server_task();
  delay(10);
}