Okay before I post my code I want to explain what is the purpose of it and what it should do.
My esp8266 is going to be in charge of my solar energy usage in my garden, which includes watering with an electronic water valve and turning on with a Relay some LED Strips.
With the following tasks:
- Watering -
- 2 periods, one at early morning and one in the evening in which it will water for some time.
- Pushing a physical button or a Blynk button while it is one of the periods will skip the current period
- Pushing the same button while it not a watering period will water for X time =“force watering”.
in case watering period is happening while “force watering” is on, force watering will stop and water period will continue is usual.
- Lights
- Currently not implemented in the code, basicaly the same as the watering just with one period from the evening to 1AM, with the option of pushing a button for turning on and off.
Note : This project is in use for 6 months in my garden with an arduino uno. The original reason for which I am moving to the NodeMCU is that I wanted to add an OLED Display and simply the uno does not have enough memory. So by moving to the NodeMCU I said to myself - Why not involving Blynk also 
For your eyes and advice -
#define BLYNK_PRINT Serial
#include <BlynkSimpleEsp8266.h>
char auth[] = "";
char ssid[] = "";
char pass[] = "";
//Display Libraries
#include "SSD1306Wire.h"
SSD1306Wire display(0x3c, D3, D5);
#include "OLEDDisplayUi.h"
#include "images.h"
OLEDDisplayUi ui(&display);
//RTC Libraries
#include <TimeLib.h>
#include <WidgetRTC.h>
WidgetRTC rtc;
//Pins Defining
int WATER_RELAY_PIN = 16; //D0
int WATER_BUTTON_PIN = 5; //D1
int LIGHT_RELAY_PIN = 4; //D2
int LIGHT_BUTTON_PIN = 0; //D3
//Timed Actions Defining
int WATER_START_1_HOUR = 6;
int WATER_START_1_MINUTE = 45;
int WATER_STOP_1_HOUR = 7;
int WATER_STOP_1_MINUTE = 15;
int WATER_START_2_HOUR = 16;
int WATER_START_2_MINUTE = 95;
int WATER_STOP_2_HOUR = 17;
int WATER_STOP_2_MINUTE = 20;
int TIME_TO_START_LIGHTS = 19;
int TIME_TO_STOP_LIGHTS = 1;
// Cacculating Watering Time To Double
double WATER_START_DOUBLE_1 = WATER_START_1_HOUR+(double(WATER_START_1_MINUTE)/60);
double WATER_STOP_DOUBLE_1 = WATER_STOP_1_HOUR+(double(WATER_STOP_1_MINUTE)/60);
double WATER_START_DOUBLE_2 = WATER_START_2_HOUR+(double(WATER_START_2_MINUTE)/60);
double WATER_STOP_DOUBLE_2 = WATER_STOP_2_HOUR+(double(WATER_STOP_2_MINUTE)/60);
//Control and Managment booleans
boolean wateringTime=false;
boolean isWatering = false;;
boolean forceWatering = false;
int skippedWaterPeriod = 0;
long startForceWateringTimeStamp;
long FORCE_WATERING_TIME_IN_MS = 9000;
boolean isLights = false;
boolean forceLights = false;
boolean lightsTime = false;
//Buttons
boolean lastWaterButtonState = false;
boolean lastLightsButtonState = false;
//runWaterLogic timing ( readCounterLimit X blynkAndButtonRead timing) == 2500ms
int readCounter=0;
int readCounterLimit=10;
//Debugging
int logCounter = 0;
BlynkTimer timer;
void setup()
{
Serial.begin(115200);
pinMode(WATER_RELAY_PIN, OUTPUT);
pinMode(WATER_BUTTON_PIN, INPUT);
pinMode(LIGHT_RELAY_PIN, OUTPUT);
pinMode(LIGHT_BUTTON_PIN, INPUT);
stopWatering(); // Stopping watering as a starting point.
WiFi.begin(ssid, pass); // Connection to a wifi network
Blynk.config(auth); // Connection to Blynk servers, 5 seconds timeout
timer.setInterval(250L, blynkAndButtonRead);
// timer.setInterval(2500L, runWaterLogic); // Watering methods
timer.setInterval(15000L, rtcCheck); // RTC Module time update every 15 seconds
}
void loop(){
timer.run();
// Data updates
//rtcCheck(); //RTC Module currently not connected -
//ui.update(); //Screen updating
if (readCounter>readCounterLimit){
runWaterLogic();
readCounter = 0;
}
}
void blynkAndButtonRead(){
if (WiFi.status()==WL_CONNECTED){
Blynk.run();
Serial.println("Blynk timer run");
}
waterButtonListen();
readCounter++;
}
BLYNK_CONNECTED() {
// Synchronize time on connection
rtc.begin();
}
void runLightsLogic(){
}
void runWaterLogic(){
Serial.println();
Serial.print("========== ");
Serial.print(logCounter++);
Serial.print(" ==========");
Serial.println();
wateringTime=waterTimeCheck();
boolean lastWateringTime=wateringTime;
//Timed Watering
if(wateringTime && skippedWaterPeriod==0){
Serial.println("It is watering time and not a skipped period");
startWatering();
}
if(skippedWaterPeriod>0){
checkSkippedWaterPeriod();
}
if(forceWatering){
checkForceWatering();
}
if(!wateringTime && lastWateringTime!=wateringTime){
stopWatering();
Serial.println("Watering time is over");
}
}
void checkSkippedWaterPeriod(){
Serial.println("--Checking is skip period has passed--");
Serial.print("Checking if current time - ");
Serial.println(getTimeAsDouble());
Serial.print("Is between ");
Serial.print(WATER_STOP_DOUBLE_1);
Serial.print(" and ");
Serial.println(WATER_START_DOUBLE_2);
Serial.print("Or is between ");
Serial.print(WATER_STOP_DOUBLE_2);
Serial.print(" and ");
Serial.println("23.99 ");
if (WATER_STOP_DOUBLE_1 < getTimeAsDouble() && getTimeAsDouble() < WATER_START_DOUBLE_2) {
Serial.println("Watering range 1 skip period has passed");
skippedWaterPeriod = 0;
}
if (WATER_STOP_DOUBLE_2 < getTimeAsDouble() && getTimeAsDouble() < 23.99) {
Serial.println("Watering range 2 skip period has passed");
skippedWaterPeriod = 0;
}
}
void checkForceWatering(){
Serial.println("Force watering calculation begun");
if (startForceWateringTimeStamp == 0) {
startForceWateringTimeStamp = millis();
Serial.println("Force watering begin is");
Serial.println(startForceWateringTimeStamp);
} if (millis() <= startForceWateringTimeStamp + FORCE_WATERING_TIME_IN_MS) {
Serial.println("Force watering begun");
Serial.println("Count is:");
Serial.println(millis());
forceWatering = true;
} else {
Serial.println("Force watering stopped");
stopForceWatering();
}
}
void waterButtonListen(){
boolean currentState = digitalRead(WATER_BUTTON_PIN);
if(currentState!=lastWaterButtonState){
Serial.println("Water button state changed");
if (currentState==true){
Serial.println("Water button pressed");
Serial.println("++++++++++++++++++++++++++++++++++");
waterButtonLogic();
}else if(currentState==false){
Serial.println("Water button Released");
}
}
lastWaterButtonState=currentState;
}
void lightsButtonListen(){
}
void waterButtonLogic(){
if (wateringTime){
Serial.println("It is watering time and button pressed");
skipCurrentWatering();
}
if(!wateringTime && forceWatering){
Serial.println("Force watering stop");
stopForceWatering();
}
else if(!wateringTime && !forceWatering){
Serial.println("Force watering begin");
startForceWatering();
}
}
void skipCurrentWatering(){
Serial.println("Skipping current timed watering");
double skippedWaterTimestamp = getTimeAsDouble();
stopWatering();
if (WATER_START_DOUBLE_1 <= skippedWaterTimestamp && skippedWaterTimestamp < WATER_STOP_DOUBLE_1) {
Serial.println("Watering range 1 is skipped");
skippedWaterPeriod = 1;
}
if (WATER_START_DOUBLE_2 <= skippedWaterTimestamp && skippedWaterTimestamp < WATER_STOP_DOUBLE_2) {
Serial.println("Watering range 2 is skipped");
skippedWaterPeriod= 2;
}
}
void startForceWatering(){
startWatering();
forceWatering=true;
}
void stopForceWatering(){
stopWatering();
Serial.println("Force watering elapsed time is ");
Serial.println((millis()-startForceWateringTimeStamp));
startForceWateringTimeStamp = 0;
Serial.println("Resetting force watering time stamp");
Serial.println("Stopping force watering");
forceWatering=false;
}
boolean lightsTimeCheck() {
if (TIME_TO_START_LIGHTS > TIME_TO_STOP_LIGHTS) {
if ((TIME_TO_START_LIGHTS <= getCurrentHour() && getCurrentHour() <= 23) || (0 <= getCurrentHour() && getCurrentHour() < TIME_TO_STOP_LIGHTS)) {
return true;
}
} else {
if ((getCurrentHour() >= TIME_TO_START_LIGHTS && getCurrentHour() < TIME_TO_STOP_LIGHTS)) {
return true;
}
}
return false;
}
boolean waterTimeCheck() {
Serial.println("Checking if watering time is now");
Serial.print("Now = ");
Serial.println(getTimeAsDouble());
if (WATER_START_DOUBLE_1 <= getTimeAsDouble() && getTimeAsDouble() < WATER_STOP_DOUBLE_1) {
Serial.println("Watering range 1 is now");
return true;
}
if (WATER_START_DOUBLE_2 <= getTimeAsDouble() && getTimeAsDouble() < WATER_STOP_DOUBLE_2) {
Serial.println("Watering range 2 is now");
return true;
}
return false;
Serial.println("Watering time is not now");
}
void startWatering() {
if (!isWatering) {
digitalWrite(WATER_RELAY_PIN, HIGH);
isWatering = true;
Serial.println("WATERING ACTIVATED");
}
else{
Serial.println("startWatering function activated but watering is already on");
}
}
void stopWatering() {
if (isWatering) {
digitalWrite(WATER_RELAY_PIN, LOW);
isWatering = false;
Serial.println("WATERING DEACTIVATED");
}
else{
Serial.println("stopWatering function activated but watering is already off");
}
}
//RTC and Timing
void rtcCheck(){
//now = clock.getDateTime();
Serial.println("RTC Clock Checked");
}
int getCurrentHour() {
return int(hour());
}
double getCurrentMinute() {
return int(minute());
}
double getTimeAsDouble() {
return double(hour()) + (double(minute()) / 60);
}