/* 
 * Our project simulates a plant sensor and action center.
 * Sensors:
 *  1. Moisture
 *  2. Light exposure
 * Automations - Inform the user via telegram when:
 *  1. the plant is dry
 *  2. The plant doesn't get enough light
 *  3. The plant is ok
 * Actions: 
 *  1. Water the plant
 *  2. Light the plant artificially.
 *  
 * The system is controlled by GUI in Blynk.com and make.com
 * 
 * The circuit in ESP32:
 *  Input - Light sensor, Moisture sensor
 *  Output - Strip light, Servo
 */

/* Fill-in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID "TMPL6FXz41QDY"
#define BLYNK_TEMPLATE_NAME "Final project"
#define BLYNK_AUTH_TOKEN "WeaNymZSOqhBNWAnf-yGqghF9KqCYIF2"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <Adafruit_NeoPixel.h>
#include <ESP32Servo.h>

// WiFi credentials.
char ssid[] = "";
char pass[] = "";

BlynkTimer timer;
Servo myservo;

// Pins initialization
const int moistureSensorPin = 33;
const int lightSensorPin = 34;
const int stripLightPin = 19;
const int servoPin = 23;

int stripLightIsOn = 0;
int streamIsOpen = 0;

Adafruit_NeoPixel strip(12, stripLightPin, NEO_GRB + NEO_KHZ800);

void sendPlantData() {
  // Read moisture level (0 to 4095) and convert to percentage
  int moistureLevel = analogRead(moistureSensorPin);
  int lightLevel = analogRead(lightSensorPin);
  int moisturePercentage = map(moistureLevel, 1000, 3700, 100, 0); // Adjust mapping as needed
  int lightPercentage = map(lightLevel, 0, 4095, 100, 0); // Adjust mapping as needed
  
  Blynk.virtualWrite(V0, moisturePercentage);
  Blynk.virtualWrite(V1, lightPercentage);
}

// Water the plant
BLYNK_WRITE(V3){
  streamIsOpen = param.asInt();
  if (streamIsOpen == 1){
    myservo.write(30);
  } else {
    myservo.write(0);
  }
}

BLYNK_WRITE(V2)
{
  stripLightIsOn = param.asInt(); // assigning incoming value from pin V1 to a variable
  if (stripLightIsOn == 1){
    strip.fill(strip.Color(255, 255, 255)); // Turn on all the LEDs (white color)
    strip.show();
  } else {
    strip.fill(strip.Color(0, 0, 0)); // Turn off all the LEDs
    strip.show();
  }
}

void setup()
{
  pinMode(moistureSensorPin, INPUT);
  pinMode(lightSensorPin, INPUT);
  myservo.attach(servoPin); // attaches the servo onto pin
  
  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
  strip.begin();
  strip.show();
  strip.setBrightness(150); // Set BRIGHTNESS to about 1/5 (max = 255)
  
  timer.setInterval(100L, sendPlantData);
}

void loop(){
  Blynk.run();
  timer.run();
}
