text: /*
    This sketch uses a capacitive Sensor to basically retrieve data and sent this data over the network.
  
    This is a very very early release version. There are a lot of features missing, like automatic connection through wifi with the appropriate android app.
    Also saving this data in the EEprom is planned.
  
  
    Changelog:
  
    - Added Wiring diagrams and board layouts
  */
  
  #include <Adafruit_NeoPixel.h>
  #include <ESP8266WiFi.h>
  #include <WiFiUdp.h>
  #include <EEPROM.h>
  
  #ifdef __AVR__
  #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
  #endif
  
  
  //Setup our WiFi Credentials. Remember if you change these you also need to change them in the App!
  #ifndef APSSID
  #define APSSID "HumiditySensor"
  #define APPSK  "FreeThePlants"
  #endif
  
  String string_Value;
  float float_Value=111.2222;
  
  
  //
  unsigned int localPort = 8888;      // local port to listen on
  
  // buffers for receiving and sending data
  char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; //buffer to hold incoming packet,
  char  ReplyBuffer[] = "ack";       // a string to send back
  
  
  int address = 0;
  int HasEEProm;
  byte Value;
  String PW = "";
  String ID = "";
  
  //Define our Sensor data, remember this is calibrated to my sensor, yours need to be calibrated individually to work properly!
  const int AnalogPin = A0;
  const int LEDPin = D1;
  const int PIN = D2;
  const int LED = D0;
  const int AirValue = 624;   //you need to replace this value with Value_1
  const int WaterValue = 186;  //you need to replace this value with Value_2
  
  int runs;
  // How many NeoPixels are attached to the Arduino?
  #define NUMPIXELS 1 // Popular NeoPixel ring size
  
  //Define our NeoPixel
  Adafruit_NeoPixel pixels(NUMPIXELS, LEDPin, NEO_GRB + NEO_KHZ800);
  IPAddress ip(192, 168, 1, 255);
  
  
  const char *ssid = APSSID;
  const char *password = APPSK;
  
  int PRed = 0;
  int PGreen = 0;
  int PBlue = 0;
  int RedVal = 0;
  int GreenVal = 0;
  int BlueVal = 0;
  
  
  WiFiUDP Udp;
  
  void setup() {
    WiFi.disconnect();
    delay(1000);
    EEPROM.begin(512);
    runs = 0;
    int conattempts = 0;
    pinMode(AnalogPin, OUTPUT);
    Serial.begin(115200);
    delay(1000);
    //Here we are checking weather the EEProms first byte is empty... if it is, we assume there is no data in there!
    Value = EEPROM.read(address);
    Serial.print(address);
    Serial.print("\t");
    Serial.print(Value, DEC);
    Serial.print("\n");
    HasEEProm = Value, DEC;
    
    if(HasEEProm){
      GetEEpromData();
      Serial.printf("EEProm contained data, starting up normally!");
      WiFi.mode(WIFI_STA);
      Serial.println();
      Serial.println(ID);
      Serial.println(PW);
      
      WiFi.begin(ID, PW);
      while (WiFi.status() != WL_CONNECTED) {
        Serial.print('.');
        delay(500);
        conattempts++;
        if (conattempts >= 20){
          //setting up our Wifi network since the connection attempts were unsuccessful!
          Serial.println("Could not connect to wifi, entering setup mode!");
              Serial.printf("EEProm empty, prepairing for setup!\n");
          //Setup our WiFi network and get ready to be set up!
          Serial.println();
          Serial.print("Configuring access point...");
          /* You can remove the password parameter if you want the AP to be open. */
          WiFi.softAP(ssid, password);
          IPAddress myIP = WiFi.softAPIP();
          Serial.print("AP IP address: ");
          Serial.println(myIP);
          Serial.printf("UDP server on port %d\n", localPort);
          Udp.begin(localPort);
          pixels.begin();
          HasEEProm = 0;
          return;
        }
      }
      
      Serial.print("Connected! IP address: ");
      Serial.println(WiFi.localIP());
      Serial.printf("UDP server on port %d\n", localPort);
      Udp.begin(localPort);
  
      //Initing our LED, remember we can scale this almost indefinetly!
      #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
      clock_prescale_set(clock_div_1);
      #endif
      
    }else{
      Serial.printf("EEProm empty, prepairing for setup!\n");
      //Setup our WiFi network and get ready to be set up!
      Serial.println();
      Serial.print("Configuring access point...");
      /* You can remove the password parameter if you want the AP to be open. */
      WiFi.softAP(ssid, password);
  
      IPAddress myIP = WiFi.softAPIP();
      Serial.print("AP IP address: ");
      Serial.println(myIP);
      Serial.printf("UDP server on port %d\n", localPort);
      Udp.begin(localPort);
    }
    pixels.begin();
  }
  
  //Mapping our Values according to calibration
  int MappedData(int RawData) {
  	int i = map(RawData, AirValue, WaterValue, 0, 100);
  	return i;
  }
  
  void SetPixels(int R, int G, int B) {
  	pixels.clear();
  	for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...
  
  	// pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
  	// Here we're using a moderately bright green color:
  		pixels.setPixelColor(i, pixels.Color(G, R, B));
  
  		pixels.show();   // Send the updated pixel colors to the hardware.
  	}
  }
  
  int CalculateStep(int prevValue, int endValue) {
    int step = endValue - prevValue; // What's the overall gap?
    if (step) {                      // If its non-zero, 
      step = 1020/step;              //   divide by 1020
    } 
    return step;
  }
  
  int CalculateVal(int step, int val, int i) {
  
    if ((step) && i % step == 0) { // If step is non-zero and its time to change a value,
      if (step > 0) {              //   increment the value if step is positive...
        val += 1;           
      } 
      else if (step < 0) {         //   ...or decrement it if step is negative
        val -= 1;
      } 
    }
    // Defensive driving: make sure val stays in the range 0-255
    if (val > 255) {
      val = 255;
    } 
    else if (val < 0) {
      val = 0;
    }
    return val;
  }
  
  //Add a fading function soon to be added
  void FadePixels(int R, int G, int B) {
  	int stepR = CalculateStep(PRed, R);
  	int stepB = CalculateStep(PBlue, B);
  	int stepG = CalculateStep(PGreen, G);
  	
  	for(int i = 0; i < 1020; i++)
  	{
  		RedVal = CalculateVal(stepR, RedVal, i);
  		GreenVal = CalculateVal(stepG, GreenVal, i);
  		BlueVal = CalculateVal(stepB, BlueVal, i);
  		SetPixels(RedVal, GreenVal, BlueVal);
  	}
  
  	PRed = RedVal; 
  	PBlue = BlueVal; 
  	PGreen = GreenVal;
  }
  
  int MainLogic() {
  	pinMode(LED, HIGH);
  	int data = MappedData(analogRead(AnalogPin));
  	return data;
  }
  
  void Main() {
  	int SensorData = MainLogic();
  	int rData = 0;
  	int gData = 0;
  	int bData = 0;
  
    //Just making sure we don't over or undershoot the Value to prevent unknown consequences with the mappings!
    if (SensorData > 100){
      SensorData = 100;
    }else if (SensorData < 0){
      SensorData = 0;
    }
  
    //Setting our RGB Values
  	if (SensorData < 50) {
  		gData = map(SensorData, 0, 87, 0, 255);
  		rData = map(SensorData, 0, 87, 255, 0);
  		FadePixels(rData, gData, 0);
      Serial.printf("Set color to red \n");
  	}
  	else if (SensorData >= 50 && SensorData < 87) {
  		gData = map(SensorData, 0, 87, 0, 255);
  		rData = map(SensorData, 0, 87, 255, 0);
  		FadePixels(rData, gData, 0);
      Serial.printf("Set color to green\n");
  	}
  	else if (SensorData >= 87) {
  		//Seperate function to display the soil is overwatered in Blue
  		rData = 0;
  		gData = map(SensorData, 87, 100, 255, 0);
  		bData = map(SensorData, 87, 100, 0, 255);
  		if (rData < 0) rData = 0;
  		FadePixels(rData, gData, bData);
      Serial.printf("Set color to Blue\n");
  	}
  	runs++;
  
  	//Write data every 10 runs or every 1 seconds to the broadcast IP address on port 4020
  	if (runs == 10) {
  		Serial.printf("Sending out our sweet payloud!\n");
  		//Let our onboard LED blink shortly
  		pinMode(LED, LOW);
  		Udp.beginPacket(ip, 4020);
  		Udp.printf("DAT|%d", SensorData);
  		Udp.endPacket();
  		runs = 0;
  	}
  
  	//let our little sensor rest a little!
  	delay(100);
  }
  
  int eeprom_strcpy(char string[]){
      ;
     int data[128];
     char a[128]= "";
     int writtenData = 0;
     strcpy(a, string);
     int x;
     for (x=0; x<strlen(a); x++){
       byte t = (int) a[x];
       EEPROM.write(x, t);
       EEPROM.commit();
       Serial.printf("%d ", t);
       writtenData++;
     }
     Serial.printf("%d", 32);
     Serial.printf("\n");
     Serial.printf("Wrote %d bytes\n", writtenData);
     GetEEpromData();
     return 0;
  }
  
  void GetEEpromData(){
    byte val;
    int hitindc = 0;
    char pw [128] = "";
    char ch = 'c';
    int x;
    int data = 0;
  
    for (x = 0; x<128; x++){
     //reading out the EEProm and saving it into a local variable
     val = EEPROM.read(x);
     data = val, DEC;
     
     if (data == 1){
        hitindc++;
        if (hitindc == 1){
          Serial.printf("id: ");
        }
        if (hitindc == 2){
          Serial.printf("pw: ");
        }
        if (hitindc == 3){
          break;
        }
        continue;
      }
      //This is when we hit the WiFis Name, so we save this into our global variable
      if (hitindc == 1){
        ch = (char) data;
        ID += (char) data;
        Serial.printf("%c", ch);
      }
      //This is basically when we hit the password, so we save this into our global variable...
      if (hitindc == 2){
        ch = (char) data;
        PW += (char) data;
        Serial.printf("%c", ch);
      }
    }
    Serial.printf("\n");
    char* res = pw;
  }
  
  void loop() {
    //digitalWrite(PIN, HIGH);
    
    if(HasEEProm){
      Main();
      return;
    }
  
    int packetSize = Udp.parsePacket();
    if (packetSize) {
      Serial.printf("Received packet of size %d from %s:%d\n    (to %s:%d, free heap = %d B)\n",
                    packetSize,
                    Udp.remoteIP().toString().c_str(), Udp.remotePort(),
                    Udp.destinationIP().toString().c_str(), Udp.localPort(),
                    ESP.getFreeHeap());
  
      // read the packet into packetBufffer
      int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
      packetBuffer[n] = 0;
      Serial.println("Contents:");
      Serial.println(packetBuffer);
      // send a reply, to the IP address and port that sent us the packet we received
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      int ref = eeprom_strcpy(packetBuffer);
      if (!ref){
        Udp.write(ReplyBuffer);
        Udp.endPacket();
      }
  
      string_Value=String(float_Value,4);
      string_Value=string_Value+";";
      for(int n=0; n< string_Value.length();n++){
        Serial.printf("%c", string_Value[n]);
      }
      Serial.printf("\n");
    }
    SetPixels(0, 0, 255);
    delay(500);
    SetPixels(0, 0, 0);
    delay(500);
  }