#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <SHT1x.h>
#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
 
// Update these with values suitable for your network.
// Achtung gleiche mac darf nicht im gleichen Netz auftauchen
byte mac[]    = {  0x90, 0xA2, 0xDA, 0x00, 0xDA, 0x9F };
IPAddress ip(192, 168,2 , 202);
IPAddress server(192, 168, 2, 71);
int W5100_RESET_PIN = 3;
// PWM LM358
int pwmOut = 5;

//sht
// Timing
unsigned long readTime;
unsigned long pubTime;
// Data
float temp_c;
float old_temp_c = 0;
float humidity;
float old_humidity;

char buffer[10];
String line0;
// Relais
const int rfrei = 6;
const int left = 7;
//Status
int state = 0;
int upm = 0;
int lefton = 0;

const int idle = 0;   // motor aus
const int work = 1;   // motor an

// Specify data and clock connections and instantiate SHT1x object
int dataPin = 2;
int clockPin =  3;
SHT1x sht1x(dataPin, clockPin);


void callback(char* topic, byte* payload, unsigned int length) {
  //Serial.print("Message arrived [");
  //Serial.print(topic);
  //Serial.print("] ");
  line0=topic;
  int x = 0;
  int y = 0;
  float p = 0;
  //Serial.println(line0);
  if (line0.endsWith("drehz")) {   
   for (int i=0;i<length;i++) {
    if (i==0) {
      x = payload[i]-'0';
    }
    if (i==1) {
      y = payload[i]-'0';
      x = x*10 + y;
    }
    if (i==2) {
      x = 100;
    }
   }
    p = x;
    p = p * 2.55;
    upm = p;
    analogWrite(pwmOut, upm); // about zero volts   
   //Serial.println(x);
   //Serial.println(p);
   //Serial.println(upm);
  }
  
  if (line0.endsWith("frei")){
    Serial.println("frei");
    
    int inByte1 = payload[0];
    int inByte2 = payload[1];
    if ((inByte1 == 'o') && (inByte2 == 'n'))
  {
    Serial.println(" on");
    digitalWrite(rfrei, LOW);
    state = work;
  }
  if ((inByte1 == 'o') && (inByte2 == 'f'))
  {
    Serial.println(" of");
    digitalWrite(rfrei, HIGH);
    state = idle;
  }
  }

if (line0.endsWith("left")){
    Serial.println("left");    
    int inByte1 = payload[0];
    int inByte2 = payload[1];
    if ((inByte1 == 'o') && (inByte2 == 'n'))
  {
    lefton = 1;
    Serial.println(" on");
    if (state == work) {
      digitalWrite(rfrei, HIGH);
      delay(10000);    
       digitalWrite(left, LOW); 
      digitalWrite(rfrei, LOW);  
    }
    else {
      digitalWrite(left, LOW);
    }
  }
  if ((inByte1 == 'o') && (inByte2 == 'f'))
  {
    lefton = 0;
    if (state == work) {
      digitalWrite(rfrei, HIGH);
      delay(10000);
      digitalWrite(left, HIGH);
      digitalWrite(rfrei, LOW);       
    }
    else {
      digitalWrite(left, HIGH);
    }
  }
  }
}
 
EthernetClient ethClient;
PubSubClient mqttClient(ethClient);
 
void reconnect() {
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect Achtung unterschiedliche "Kennung"
    if (mqttClient.connect("arduinoKeller")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      mqttClient.publish("outTopic","hello world");
      // ... and resubscribe
      mqttClient.subscribe("/keller/set/#");
    } else {
      Serial.print("failed, rc=");
      //Serial.print(ethClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
 
void setup(){

  Serial.begin(57600);
  // RC-Brücke GND -- Reset behebt das Startproblem des Ethernetshields 220uF 330R 
  Serial.println(F("node starting..."));
  pinMode(W5100_RESET_PIN, OUTPUT);
  digitalWrite(W5100_RESET_PIN, LOW);
  delay(100);
  digitalWrite(W5100_RESET_PIN, HIGH);
  // give the Ethernet shield a second to initialize:
  delay(1000);

  pinMode(pwmOut, OUTPUT);
  pinMode(rfrei,OUTPUT);
  pinMode(left,OUTPUT);
  digitalWrite(left, HIGH);
  lefton = 0;
  digitalWrite(rfrei, HIGH);
  state = idle;
  upm = 0;
  analogWrite(pwmOut, upm); 
  
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
 
  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
  reconnect();
}

void pub_Temp(){
 pubTime = millis(); 
 dtostrf(state,1,1,buffer);
 mqttClient.publish("/keller/state", buffer);
  dtostrf(lefton,1,1,buffer);
 mqttClient.publish("/keller/lefton", buffer);
 dtostrf(upm,1,1,buffer);
 mqttClient.publish("/keller/upm", buffer);
  dtostrf(humidity, 6, 2, buffer);
  mqttClient.publish("/keller/humidity", buffer);
   dtostrf(temp_c, 6, 2, buffer);
  mqttClient.publish("/keller/temp", buffer);
    Serial.print("Sending... ");
    Serial.print("Temp: ");
    Serial.print(String(temp_c));
    Serial.print(" Humidity: ");
    Serial.print(String(humidity));  
    Serial.print(" State : ");
    Serial.print(String(state));  
    Serial.print(" lefton : ");
    Serial.print(String(lefton));  
    Serial.print(" upm : ");
    Serial.println(String(upm));  
}

void readTemp(){
 readTime = millis(); 
 temp_c = sht1x.readTemperatureC();
 humidity = sht1x.readHumidity();
 dtostrf(temp_c, 6, 2, buffer);
 // inititialisierung
 if (old_temp_c == 0) old_temp_c = temp_c;
}

 
void loop()
{
  mqttClient.loop();

//analogWrite(pwmOut, 0); // about zero volts

  
  if (!mqttClient.connected())
  {
    reconnect();
  }
  
  if(millis() > readTime+500){
    readTemp();
  }
  if(millis() > pubTime+1000){
    pub_Temp();
  }

}
