Skip to content

Instantly share code, notes, and snippets.

@Andymulb
Created January 5, 2021 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Andymulb/3b6a4b1f43533e16c88c08682613697f to your computer and use it in GitHub Desktop.
Save Andymulb/3b6a4b1f43533e16c88c08682613697f to your computer and use it in GitHub Desktop.
ESP32 Soil Moisture Sensor with Tingg MQTT and Telegram integration
/*
Plant Wartering Alert & Monitor
Components: ESP32, Capacitive Soil Moisture Sensor, Micro-USB Cable, Power Supply, Jumper Wires
By Andreas Blum Media (https://blummedia.de)
*/
#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>
//------------Customize--------------
#define CHAT_ID "123456789" //Define unique Chat ID of User
#define BOTtoken "1234567890:ABC_1A2B3C4D5E6F7G8H9I" //Define unique ID Token of Telegram Bot
const String plant = "PFLANZENNAME"; //Define unique name of plant
const int trigger = 20; //Trigger Telegram message for moisture level below trigger value in percent
const char* ssid = "SSID_OF_WIFI_ROUTER";
const char* password = "WIFI_PASSWORD";
const char* mqttDeviceId = "UNIQUE_TINGG_DEVICE_ID";
const char* mqttPassword = "DEVICE_PASSWORD";
//----------Check Config Settings----------
// Topics Config
const char* soilMoistureTopic = "Soil_Moisture";
const char* levelTopic = "Level";
const char* subTopic = "Soil_Moisture";
// Tingg Config
const char* mqttServer = "mqtt.tingg.io";
const char* mqttUsername = "thing";
const int port = 1883;
// Pins Config
//const int LightPin = 0;
const int sensorPin = 32;
const int DefaultPin = 2;
WiFiClient espClient;
PubSubClient client(espClient);
//Telegram Wifi Setup
WiFiClientSecure telegramClient;
UniversalTelegramBot bot(BOTtoken, telegramClient);
//Checks for new messages every 1 second.
int botRequestDelay = 1000;
unsigned long lastTimeBotRan;
// Vars
char buf[12];
const int wet = 1500;
const int dry = 0;
int tinggPostDelay = 5000;
unsigned long lastTinggPost;
const int iTemp = 3600 / 5; //Water shortage trigger delay
const int iRestartDelay = 120; //Restart delay if trying to reconnect to MQTT
int iRestart = iRestartDelay; //Restart Counter
int iStep = 0;
int iCounter = iTemp;
int iToggle = 0;
// Function to validate connection with the board
void blinking_loop(){
while (ssid == "SSID") {
digitalWrite(DefaultPin,HIGH);
delay(500);
digitalWrite(DefaultPin,LOW);
delay(500);
Serial.println("Default light should be blinking. Please set up your Wifi configuration.");
}
}
void setup_wifi() {
delay(10);
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
iRestart = iRestartDelay * 5;
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
if (iRestart <= 0) {
Serial.print("Restarting...");
ESP.restart();
}
iRestart--;
}
randomSeed(micros());
Serial.println("");
Serial.print("Congratulations!! WiFi connected on IP address: ");
Serial.println(WiFi.localIP());
Serial.println("");
Serial.println("Now, follow up on the steps for the MQTT configuration. ");
}
void reconnect() {
while (!client.connected()) {
Serial.println("Attempting to connect MQTT...");
if (client.connect(mqttDeviceId, mqttUsername, mqttPassword)) {
Serial.println("connected");
client.subscribe(subTopic);
iRestart = iRestartDelay;
} else {
if (iRestart <= 0) {
Serial.print("Restarting...");
ESP.restart();
}
iRestart--;
Serial.print("iRestart = ");
Serial.println(iRestart);
Serial.print(" Still not connected..."); // Serial.print(client.state());
Serial.println(" trying again in 5 seconds"); // Wait 5 seconds before retrying
delay(5000);
}
}
}
//Telegram Functions
// Get sensor readings and return them as a String variable
String getReadings(){
int sensorVal = 4095 - analogRead(sensorPin);
int moisturePercentage = map(sensorVal, dry, wet, 0, 100);
if (moisturePercentage > 100) {
moisturePercentage = 100;
} else if (moisturePercentage < 0) {
moisturePercentage = 0;
}
String message = plant + "\n";
message += "Moisture: " + String(sensorVal) + "\n";
message += "Level: " + String(moisturePercentage) + " % \n";
return message;
}
//Handle what happens when you receive new messages
void handleNewMessages(int numNewMessages) {
Serial.println("handleNewMessages");
Serial.println(String(numNewMessages));
for (int i=0; i<numNewMessages; i++) {
// Chat id of the requester
String chat_id = String(bot.messages[i].chat_id);
if (chat_id != CHAT_ID){
bot.sendMessage(chat_id, "Unauthorized user", "");
continue;
}
// Print the received message
String text = bot.messages[i].text;
Serial.println(text);
String from_name = bot.messages[i].from_name;
if (text == "/start") {
String welcome = "Welcome, " + from_name + ".\n";
welcome += "Use the following command to get current readings.\n\n";
welcome += "/state \n";
bot.sendMessage(chat_id, welcome, "");
}
if (text == "/state") {
String readings = getReadings();
bot.sendMessage(chat_id, readings, "");
}
}
}
//Main Functions
void setup() {
//pinMode(LightPin,OUTPUT);
pinMode(sensorPin,INPUT);
pinMode(DefaultPin,OUTPUT);
Serial.begin(9600);
blinking_loop();
setup_wifi();
client.setServer(mqttServer, port);
bot.sendMessage(CHAT_ID, plant + " restarted!", ""); //Send message if controller restarted
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
int sensorVal = analogRead(sensorPin);
sensorVal = 4095 - sensorVal;
int moisturePercentage = map(sensorVal, dry, wet, 0, 100);
if (moisturePercentage > 100) {
moisturePercentage = 100;
} else if (moisturePercentage < 0) {
moisturePercentage = 0;
}
if (millis() > lastTinggPost + tinggPostDelay) {
Serial.print("Value: ");
Serial.println(sensorVal);
Serial.print("Level: ");
Serial.print(moisturePercentage);
Serial.println("%");
client.publish(soilMoistureTopic,itoa(sensorVal, buf, 10));
client.publish(levelTopic,itoa(moisturePercentage, buf, 10));
//Send Telegram Message if Moisture Level
switch (iStep) {
case 0:
iCounter = iTemp;
iToggle = 1;
iStep = 1;
break;
case 1:
if (iCounter <= 0) {
iStep = 2;
iToggle = 1;
} else if (moisturePercentage < trigger) {
iCounter--;
Serial.print("Counter: ");
Serial.println(iCounter);
} else if (moisturePercentage >= trigger) {
iStep = 0;
}
break;
case 2:
if (moisturePercentage < trigger && iToggle == 1) {
String alert = plant + " gießen!";
bot.sendMessage(CHAT_ID, alert, "");
Serial.println("Message sent!");
iToggle = 0;
} else if (moisturePercentage > trigger) {
iCounter = iTemp;
iStep = 3;
}
break;
case 3:
if (iCounter <= 0 && moisturePercentage > trigger) {
iStep = 0;
} else if (moisturePercentage > trigger) {
iCounter--;
Serial.print("Counter: ");
Serial.println(iCounter);
} else if (moisturePercentage <= trigger) {
iStep = 2;
}
break;
}
lastTinggPost = millis();
}
//Telegram Message Request
if (millis() > lastTimeBotRan + botRequestDelay) {
int numNewMessages = bot.getUpdates(bot.last_message_received + 1);
while(numNewMessages) {
Serial.println("got response");
handleNewMessages(numNewMessages);
numNewMessages = bot.getUpdates(bot.last_message_received + 1);
}
lastTimeBotRan = millis();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment