Automatic Plant Watering Messenger (using Telegram)

by sipandrei in Living > Gardening

461 Views, 4 Favorites, 0 Comments

Automatic Plant Watering Messenger (using Telegram)

waterNotificationBot.png

This is a quick and easy IOT project, that I've made at the request of my girlfriend, which helps you remember to water your much loved plants by sending messages via a Telegram bot, giving you a more hand-on experience than an automatic pump.

It works by connecting to a WiFi network(using the WiFiManager arduino library) and then sending messages through a Telegam bot depending on the moisture level of the soil.

This project requires you to have two environment variables:

  1. PLANT_NOTE_BOT - the telegram bot api key
  2. CHAT_ID - the ID of the chat in which you want it to send messages
  3. BOT_NAME - name of the bot

Here is a link for the GitHub repo - https://github.com/sipandrei/espPlantNotificationBot

Supplies

For this project you need two components and some jumper wires:

  1. an ESP8266 develompent board
  2. a soil moisture sensor(i recommend a capacitive one because it does not rust)

You will also need acces to a power socket and a WiFi connection

Doing the Wiring

waterNotificationBot.png

Starting out easy with connecting our two components!

The moisture sensor has three wires, one positive, one negative and a signal wire

  1. Connect the positive cable(+) to the 5V pin on your development board
  2. Connect the negative cable(-) to the GND pin on your development board
  3. Connect the signal wire to an analog pin(in my code that is A0)

Installing the Libraries

This project uses a couple of libraries that you need to install:

  1. Universal Telegram Bot - https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot - zip file
  2. WiFiManager - https://github.com/tzapu/WiFiManager - library manager
  3. ArduinoJson - https://github.com/bblanchon/ArduinoJson - library manager

For the library manager do this:

Sketch -> Include Libraries -> Manage Libraries 

For .Zip libraries do this:

Sketch -> Include Libraries -> Add .ZIP Library

Set Up the Telegram Bot

For this you will need a telegram account - https://web.telegram.org/

Make a new bot using @BotFather

Set up the commands:

  1. for adjusting the minimum soil humidity : /setmin
  2. for getting a humidity reading: /humidity

Set Up the Environment Variables

Untitled.png

I am using the Arduino IDE so i used environment variables by defining them inside a header file that I have placed in the libraries folder and then included it in the project.

The credentials.h file should have this structure:

#define PLANT_NOTE_BOT "<the api key of the bot from BotFather>"
#define CHAT_ID "<the id of the chat in which you want your bot to send messages>"
#define BOT_NAME "<the name of the robot you created>"

Program the Development Board

And now, the last big step is programming the board by uploading the following code:

#include <UniversalTelegramBot.h>
#include <WiFiClientSecure.h>
#include <WiFiManager.h>
#include <credentials.h>
#include <ArduinoJson.h>

X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure secured_client;
UniversalTelegramBot bot(PLANT_NOTE_BOT, secured_client);
const unsigned long SCAN_DELAY = 1000;
unsigned long lastScan;

extern "C"
{
  #include <lwip/icmp.h> // needed for icmp packet definitions
}
int soilSensorInput, soilSensorPercentage;
int baselineAir = 680;
int baselineWater = 280;
int minimumPercentage = 35;
bool watered = true;
bool waitMin = false;


IPAddress local_IP(192, 168, 100, 36);
IPAddress gateway(192,168,100,1);
IPAddress subnet(255,255,255,0);
IPAddress dns(8,8,8,8);
const int DNS_PORT = 53;

void percentageLimiter(int &percentageReading){
  if(percentageReading < 0)
    percentageReading = 0;
    else if(percentageReading > 100)
     percentageReading = 100;
}


void configModeCallback(WiFiManager *wifiManager){
  Serial.println("entered config mode");
  Serial.println(WiFi.softAPIP());
}


void messagesHandler(int numNewMessages){
 Serial.printf("\n Received %d new messages \n", numNewMessages);
  String response;
  for(int i = 0; i < numNewMessages; i++){
    telegramMessage &msg = bot.messages[i];
    Serial.print("Message " + msg.text);
    Serial.print(numNewMessages);
    Serial.print(i);
    if(msg.text == "/setmin" || msg.text == "/setmin@plantnote_bot"){
        waitMin = true;
        response = "Set the minimum humidity  by replying with a number between 5 and 90";
    } else if(msg.text.toInt() >= 5 && msg.text.toInt() <= 90 && waitMin == true){
        waitMin = false;
        minimumPercentage = msg.text.toInt();
        response = "Minimum percentage set to " + msg.text;
      } else if(msg.text == "/humidity" || msg.text == "/humidity@plantnote_bot"){
          response = "Current humidity is " + String(soilSensorPercentage) + "%";
        } else {
        response = "That was not a valid input";
      }
    bot.sendMessage(msg.chat_id, response, "Markdown");
  }
}


void setup() {
  WiFi.mode(WIFI_STA);
  WiFiManager wifiManager;
  bool res;
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("");


  wifiManager.setAPCallback(configModeCallback);
  wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
  res = wifiManager.autoConnect(BOT_NAME);
  Serial.println(WiFi.localIP());


  if(!res){
    Serial.print("DID NOT CONNECT");
    ESP.restart();}
   else {
    secured_client.setTrustAnchors(&cert);
    Serial.print("Retrieving time: ");
    configTime(0, 0, "pool.ntp.org"); // get UTC time via NTP
    time_t now = time(nullptr);
    while (now < 24 * 3600)
    {
      Serial.print(".");
      delay(100);
      now = time(nullptr);
    }
    Serial.println(now);
    Serial.print("Sending message to ");
    Serial.println(CHAT_ID);
    bot.sendMessage(CHAT_ID, "Plant bot started, minimum moisture - 35%", "");
  }
}


void loop() {
  soilSensorInput = analogRead(A0);
  soilSensorPercentage = map(soilSensorInput,baselineAir,baselineWater, 0, 100);
  percentageLimiter(soilSensorPercentage);
   
  if(millis() - lastScan > SCAN_DELAY){
    int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    Serial.print(numNewMessages);
    while (numNewMessages)
    {
      Serial.println("got response");
      messagesHandler(numNewMessages);
      numNewMessages = bot.getUpdates(bot.last_message_received + 1);
    }
    Serial.print(numNewMessages);
    lastScan = millis();
  }
 
  if(waitMin == false){
    if(soilSensorPercentage < minimumPercentage && watered == true){
     watered = false;
      Serial.print("Plant needs water!! Current humidity: ");
      Serial.println(soilSensorPercentage);
      bot.sendMessage(CHAT_ID, "*ALERT!! PLANT NEEDS WATER!!* Current percentage: ", "Markdown");
      bot.sendMessage(CHAT_ID, String(soilSensorPercentage),"");
   } else if(soilSensorPercentage >= minimumPercentage && watered == false){
      watered = true;
      Serial.print("Plant plant *watered*! Current humidity: ");
      Serial.println(soilSensorPercentage);
      bot.sendMessage(CHAT_ID, "Plant *watered*!", "");
    }
  }
}

Connect the Device to Wifi

Now that you have uploaded the code you need to connect the cot to the internet, that can be done by connecting to the acces point with the name of your bot, from your phone, and then access the WiFiManager portal, either by being automatically redirected or by accessing it at the address:

10.0.1.1

From there you will be able to connect to the home WiFi network

Use It!

Now that you have a fully functional bot all you need to do is to place the sensor in the soil near the plant and plug it in!

If the connection to the WiFi succeeds you will get a notification on Telegram saying Plant bot started, minimum moisture - 35%

The bot will automatically send a telegram message if the moisture of the soil gets below the threshold, which can be modified with the command:

/setmin

and then replying to the message it sends with a number from 5 to 90

You can also get the current moisture by sending this command:

/humidity


After you water the plant you also get a message for confirmation