#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
//#include <SHT1x.h>
#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
#include <DS1631.h>
#include <AccelStepper.h>
DS1631 Temp1(0);  // ini
 
// Update these with values suitable for your network.
byte mac[]    = {  0x90, 0xA2, 0xDA, 0x00, 0xDA, 0x9C };
IPAddress ip(192, 168,2 , 241);
IPAddress server(192, 168, 2, 71);

//Motor
// The X Stepper pins
#define STEPPER1_DIR_PIN 7
#define STEPPER1_STEP_PIN 6
AccelStepper stepper1(AccelStepper::FULL2WIRE,STEPPER1_STEP_PIN, STEPPER1_DIR_PIN);
int motorOn = 1;
int motorSpeed = 50;
int motorMaxSpeed = 1000;
//Relais
//Relaissatz + Peltiersteuerung
int relaispin = 3;
boolean relais = false;  // true = heizen false = kühlen
boolean aktrelais = false;
int powerpin = 2;
int power = 1;          // Vorseinstellung für die Power
int aktpower=0;  
//Thermistor zum Schutz
int t1apin = 0;
int notfall = 80;     // maximale Temperatur des Systems
int t1 =0;   
// Temperaturregulation zunächst größer 0 ;
int targetTemp = 0;     // Automatik ist aus

unsigned long pubTime;
// Data
char buffer[10];
String line0;

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);

 void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("]  Länge ");
  Serial.print(length);
  line0 =topic;
  //Zieltemperatur
  if (line0.endsWith("targettemp")) { 
  int x = 0;
  int y = 0; 
   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;
    }
   }
    targetTemp=x;
    Serial.print(" Zieltemperatur ");
    Serial.println(targetTemp);
  }  
  //Motorsteuerung
  if (line0.endsWith("drehz")) { 
  int x = 0;
  int y = 0; 
   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;
    }
   }
    motorSpeed=x;
    stepper1.setSpeed(motorSpeed*100);
    Serial.print(" Motorspeed ");
    Serial.println(motorSpeed);
  }
   if (line0.endsWith("motor")){
    int inByte1 = payload[0];
     if (inByte1 == '0'){
     motorOn = 0; 
    }
    if (inByte1 == '1'){
     motorOn = 1; 
    }   
    Serial.print(" motorON ");
    Serial.println(motorOn);
   }
   if (line0.endsWith("power")){
    int inByte1 = payload[0];
     if (inByte1 == '1'){
       aktpower = HIGH;
       digitalWrite(powerpin,aktpower);           
    }    
    if (inByte1 == '0'){
       aktpower = LOW;
       digitalWrite(powerpin,aktpower);           
    }
    Serial.print(" aktpower ");
    Serial.println(aktpower);
   }
   if (line0.endsWith("relais")){
    int inByte1 = payload[0];
         if (inByte1 == '1'){
       aktrelais = HIGH;
       digitalWrite(relaispin,aktrelais);           
    }    
   if (inByte1 == '0'){
       aktrelais = LOW;
       digitalWrite(relaispin,aktrelais);           
    } 
    Serial.print(" aktrelais ");
    Serial.println(aktrelais);  
   } 
 }
 
void reconnect() {
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttClient.connect("arduinoThermoskanne")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      mqttClient.publish("/maschine","hello world");
      // ... and resubscribe
      mqttClient.subscribe("/maschine/cmd/#");
    } else {
      Serial.print("failed, rc=");
      //Serial.print(ethClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(1000);
    }
  }
}
void setup()
{
  Serial.begin(115200);
  pinMode(relaispin,OUTPUT);
  pinMode(powerpin,OUTPUT);
  digitalWrite(relaispin,aktrelais);
  digitalWrite(powerpin,aktpower);
  Wire.begin(); // start up I2C bus
  delay(500);
  // scan();
  stepper1.setMaxSpeed(motorMaxSpeed*100);
  stepper1.setSpeed(motorSpeed*100);  
  delay(1500);
  int config = Temp1.readConfig();
  Temp1.writeConfig(13);  // Set to 12-bit, 1-shot mode
  config = Temp1.readConfig();    
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
  reconnect();
  pubTime = millis();
}

void checkTargetTemp(){
  float tist = Temp1.readTempOneShot();
  int takt = (int)tist;
  int tdelta = targetTemp - takt;    // 10-20 aktrelais LOW -> kühlen  |  aktrealis HIGH -> heizen
  Serial.println(tdelta);
    if ( aktrelais == LOW){  // Kühlen
      if (tdelta < 0){ 
        aktpower = HIGH;
        digitalWrite(powerpin,aktpower);    
        Serial.println("Power bleibt On");
        mqttClient.publish("/maschine/status", "Power On");
      } else {
        aktpower = LOW;
        digitalWrite(powerpin,aktpower);    
        Serial.println("Power Off");
        mqttClient.publish("/maschine/status", "Power Off");  
      }
    } else {                // Heizen
      if (tdelta < 0){ 
        aktpower = LOW;
        digitalWrite(powerpin,aktpower);    
        Serial.println("Power OFF");
         mqttClient.publish("/maschine/status", "Power Off");
      } else {
        t1 = float(Thermistor(analogRead(0)));
        int i =  (int)t1;
        targetTemp ;
        Serial.print(i);
        Serial.print(targetTemp);
        i = i - targetTemp;
        Serial.println(i);
        if (i<1){
          aktpower = HIGH;
          digitalWrite(powerpin,aktpower);    
          Serial.println("Power ON");  
          mqttClient.publish("/maschine/status", "Power On");
        }
      }
    }
}

void loop()
{
  if (motorOn== 1) {
    stepper1.runSpeed();
  }
  mqttClient.loop();
  if (!mqttClient.connected())
  {
    reconnect();
  }
  if(millis() > pubTime+5000){
    pub_Temp(); 
    if (targetTemp > 0){
      checkTargetTemp();
    }      
  }
}

void pub_Temp(){
  pubTime = millis(); 
  float tist = Temp1.readTempOneShot();
  dtostrf(tist, 6, 2, buffer);
  mqttClient.publish("/maschine/temp", buffer);
  Serial.print(" I2C Temp ");
  Serial.println(tist);
  t1 = float(Thermistor(analogRead(0)));
  dtostrf(t1, 6, 2, buffer);
  mqttClient.publish("/maschine/thermistor", buffer);
  Serial.print(" Thermistor ");
  Serial.println(t1);  
  int i = (int) t1;
  if (i > notfall){
        targetTemp = 0;   
        aktpower = LOW;
        digitalWrite(powerpin,aktpower);    
        Serial.println("Notfall");
        mqttClient.publish("/maschine/status", "Notfall HOT !!");  
  }
}

double Thermistor(int RawADC) {
 double Temp;
 Temp = log(10000.0*((1024.0/RawADC-1)));
//         =log(10000.0/(1024.0/RawADC-1)) // for pull-up configuration
 Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
 Temp = Temp - 273.15;            // Convert Kelvin to Celcius
//Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
 return Temp;
}

/*
void scan(){
Serial.println(" Scanning I2C Addresses");
uint8_t cnt=0;
for(uint8_t i=0;i<128;i++){
  Wire.beginTransmission(i);
  uint8_t ec=Wire.endTransmission(true);
  if(ec==0){
    if(i<16)Serial.print('0');
    Serial.print(i,HEX);
    cnt++;
  }
  else Serial.print("..");
  Serial.print(' ');
  if ((i&0x0f)==0x0f)Serial.println();
  }
Serial.print("Scan Completed, ");
Serial.print(cnt);
Serial.println(" I2C Devices found.");
}
*/
