// - Messung des Niveaus des Wasserstandes des Teiches Pin 8
// - Schalten eines elektromagnetischen Ventils R2 12Volt
// - Schalten eine Teichpumpe R1 220Volt
// ////////- Kommunikation über Ethernet  192.168.2.44:10000 <-> 192.168.2.5:10000
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

#include <NewPing.h>
 
#define TRIG_PIN 7
#define ECHO_PIN 6
#define MAX_DIST 40

#define ITERATIONS     10 // Number of iterations.
#define PING_INTERVAL 33 // Milliseconds between sensor pings (29m
unsigned long pingTimer[ITERATIONS]; // Holds the times when the next ping should happen for each iteration.
unsigned int cm[ITERATIONS];         // Where the ping distances are stored.
uint8_t currentIteration = 0;        // Keeps track of iteration step.

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DIST); // NewPing initialisieren

//#include <SHT1x.h>
#include <Wire.h>  // Only needed for Arduino 1.6.5 and earlier
// I2C d -- SDA -- green -- Analog In 4
// I2C c -- SCK -- blue  -- Analog In 5
extern "C" { 
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}
#define DEBUG 1



#define CARD_ADR 0x20 // address 0100000
boolean r1,r2,r3,r4,r5,r6,r7,r8;
byte oldRelais=0;
// Update these with values suitable for your network.
byte mac[]    = {  0x90, 0xA2, 0xDA, 0x00, 0xDA, 0x9C };
IPAddress ip(192, 168,2 , 203);
IPAddress server(192, 168, 2, 71);


// Timing
unsigned long readTime;
unsigned long pubTime;
unsigned long statusTime;

char buffer[10];
String line0;

EthernetClient ethClient;
PubSubClient mqttClient(ethClient);


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

void sendStatus(){
  statusTime = millis();
  int r = B00000000;
  if (r1) r=r | B00000001;
  if (r2) r=r | B00000010;
  if (r3) r=r | B00000100;
  if (r4) r=r | B00001000;
  if (r5) r=r | B00010000;
  if (r6) r=r | B00100000;
  if (r7) r=r | B01000000;
  if (r8) r=r | B10000000;  
  itoa(r,buffer,10);
  mqttClient.publish("/teich/relais", buffer);     
}
void relaisReset(){
    byte r = B00000000;
    Wire.beginTransmission(CARD_ADR); 
    Serial.print("send ");
    Wire.write(r);
    Wire.endTransmission();   
}

void relaisProcess(){
  byte r = B00000000;
  if (r1) r=r | B00000001;
  if (r2) r=r | B00000010;
  if (r3) r=r | B00000100;
  if (r4) r=r | B00001000;
  if (r5) r=r | B00010000;
  if (r6) r=r | B00100000;
  if (r7) r=r | B01000000;
  if (r8) r=r | B10000000;  
  if (r!=oldRelais){
    Wire.beginTransmission(CARD_ADR);
    Serial.print("send ");
    Wire.write(r);
    Wire.endTransmission(); 
    //sendStatus();
  }
  oldRelais = r;
  Serial.println(r,DEC);
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  line0 = topic;
  if (line0.endsWith("wasser")) {
    int payload_int = 0;
    for(int i=0;i<length;i++){
      char c = payload[i];
      if (c >= '0' && c <= '9')
        payload_int = payload_int*10 + c - '0';  //einzelne Ziffern zu einem Integer zusammenfügen
      else {
        Serial.print ((int)c);
        Serial.println(" war so nicht erwartet");
      }
    }
   // Serial.println(payload_int);
  }
  else {   
    boolean ron = false;
    int inByte1 = payload[0];
    int inByte2 = payload[1];
    if ((inByte1 == 'o') && (inByte2 == 'n'))
      {
         Serial.println(" on");
         ron=true;
      }
    if ((inByte1 == 'o') && (inByte2 == 'f'))
      {
        Serial.println(" of");
        ron = false;
      }
    if (line0.endsWith("r1"))
     {
      Serial.print(" r1 ");
      Serial.println(ron);
      r1=ron;
     }
   if (line0.endsWith("r2"))
     {
      Serial.print(" r2 ");
      Serial.println(ron);
      r2=ron;
    }    
   if (line0.endsWith("r3"))
     {
      Serial.print(" r3 ");
      Serial.println(ron);
      r3=ron;
    }  
     if (line0.endsWith("r4"))
     {
      Serial.print(" r4 ");
      Serial.println(ron);
      r4=ron;
    }      
     if (line0.endsWith("r5"))
     {
      Serial.print(" r5 ");
      Serial.println(ron);
      r5=ron;
    }      
     if (line0.endsWith("r6"))
     {
      Serial.print(" r6 ");
      Serial.println(ron);
      r6=ron;
    }      
     if (line0.endsWith("r7"))
     {
      Serial.print(" r7 ");
      Serial.println(ron);
      r7=ron;
     }  
     if (line0.endsWith("r8"))
     {
      Serial.print(" r8 ");
      Serial.println(ron);
      r8=ron;
     }   
  relaisProcess();
        
 }         
}
 

 
void reconnect() {
  // Loop until we're reconnected
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttClient.connect("arduinoClient")) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      mqttClient.publish("Teich","hello world");
      // ... and resubscribe
      mqttClient.subscribe("/teich/#");
    } else {
      Serial.print("failed, rc=");
      //Serial.print(ethClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

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.");
}
 
void setup()
{
  Wire.begin();  
  Serial.begin(57600);

  pingTimer[0] = millis() + 75;            // First ping starts at 75ms, gives time for the Arduino to chill before starting.
  for (uint8_t i = 1; i < ITERATIONS; i++) // Set the starting time for each iteration.
  pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;

  
  //scan();
  relaisReset();
  mqttClient.setServer(server, 1883);
  mqttClient.setCallback(callback);
  Ethernet.begin(mac, ip);
  // Allow the hardware to sort itself out
  delay(1500);
  reconnect();
}

void pub_Temp(){
  int sum = 0;
  pubTime = millis(); 
  int i = sonar.ping_cm();
  //Serial.println(i);
  if (i > 0) {
    if (currentIteration < ITERATIONS){
      cm[currentIteration] = i;
      currentIteration += 1;
      //Serial.println(currentIteration);
    } else {      
      for (int i=0; i<ITERATIONS;i++) {
        sum += cm[i];
        //Serial.print(sum);
      }
      sum = sum / ITERATIONS;
      //Serial.print(" sum ");
      currentIteration = 0;      
      itoa(sum,buffer,10);
      Serial.println(sum);
      mqttClient.publish("/teich/wasser", buffer);
    }
  }    
}

void loop()
{
  mqttClient.loop();
  if (!mqttClient.connected())
  {
    reconnect();
  }
  if(millis() > pubTime+1000){ 
    pub_Temp();      
  }
  if(millis() > statusTime+5000){ 
    sendStatus();     
  }  
}
