Hi all - I have got my ESP32 to send me emails, no problem, and I have got a separate
sketch working fine (monitoring the level of salt in a water softener, and sounding a buzzer every 15 minutes if the level gets below the threshold). But I want to get my code to send me an email when the salt level is low. I've spent a lot of time trying to combine the code, and got down to one compilation error (initially 50+ errors!!), but I just can't see where I have gone wrong. Is there a tutorial showing how to use the email sending code in your own sketch? I could not find one.
This is my first time using any microcontroller, so I suspect my error is an obvious one to anyone else!
Here's the code: I start by defining the pins for the salt level monitor part, and then paste all the email sketch set up parts, and then try to send a mail from within my code.
// Define pins for the ultrasonic sensor
const int echoPin = 25;
const int trigPin = 26;
//Define other pins
const int buzzerPin = 27; // The GPIO pin for the buzzer
const int testPin = 13; // The GPIO pin for the "Test" switch input. When switched to "Test" position, the "Test" switch connects pin 13 to Ground, giving a LOW state.
// Pin 13 is connected to 3V3 via a 10K Ohm resistor. to prevent pin 13 floating to unkown states when in normal operation.
int testState = 0; //initialise the test variable to zero
unsigned long previousMillis = 0; // will store last count time salt level was tested
const long interval = 900000; // interval at which to test the salt level (900,000 milliseconds = 15 minutes)
#include <Arduino.h>
#include <WiFi.h>
#include <ESP_Mail_Client.h>
#define WIFI_SSID "*********" //Our wifi SSID
#define WIFI_PASSWORD "********"
/** The smtp host name e.g. smtp.gmail.com for GMail or smtp.office365.com for Outlook or smtp.mail.yahoo.com */
#define SMTP_HOST "smtp.gmail.com
#define SMTP_PORT 465
/* The sign in credentials */
#define AUTHOR_EMAIL "*******@gmail.com"
#define AUTHOR_PASSWORD "**** **** **** ****"
/* Recipient's email*/
#define RECIPIENT_EMAIL "****@gmail.com" //my email
#define RECIPIENT_CC1 "****@gmail.com"//wife's email as a CC:
/* Declare the global used SMTPSession object for SMTP transport */
SMTPSession smtp;
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status);
void setup()
{
// Begin serial communication at 9600 baud rate
Serial.begin(9600);
pinMode(buzzerPin, OUTPUT); // initialize digital pin buzzerPin as an output.
pinMode(trigPin, OUTPUT); // initialise digital pin trigPin as an output
pinMode(echoPin, INPUT); // initialize digital pin echoPin as an input
pinMode(testPin, INPUT); // initialise digital pin testPin as an input
}
void loop()
{
Serial.println();
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(300);
}
Serial.println();
Serial.print("Connected with IP: ");
Serial.println(WiFi.localIP());
Serial.println();
/* Set the network reconnection option */
MailClient.networkReconnect(true);
/** Enable the debug via Serial port
* 0 for no debugging
* 1 for basic level debugging
*/
smtp.debug(1);
/* Set the callback function to get the sending results */
smtp.callback(smtpCallback);
/* Declare the Session_Config for user defined session credentials */
Session_Config config;
/* Set the session config */
config.server.host_name = SMTP_HOST;
config.server.port = SMTP_PORT;
config.login.email = AUTHOR_EMAIL;
config.login.password = AUTHOR_PASSWORD;
config.login.user_domain = "";
//Set the NTP config time
config.time.ntp_server = F("europe.pool.ntp.og,time.nist.gov");// set to Europe server
config.time.gmt_offset = 0;
config.time.day_light_offset = 0;
/* Declare the message class */
SMTP_Message message;
/* Set the message headers */
message.sender.name = F("ESP");
message.sender.email = AUTHOR_EMAIL;
message.subject = F("From your Water Softner");
message.addRecipient(F("Steve"), RECIPIENT_EMAIL);
message.addCc(RECIPIENT_CC1); //Jill is on CC:
//Send raw text message
String textMsg = "Low salt alarm";//this is the mesage I want to send
message.text.content = textMsg.c_str();
message.text.charSet = "us-ascii";
message.text.transfer_encoding = Content_Transfer_Encoding::enc_7bit;
message.priority = esp_mail_smtp_priority::esp_mail_smtp_priority_low;
message.response.notify = esp_mail_smtp_notify_success | esp_mail_smtp_notify_failure | esp_mail_smtp_notify_delay;
/* Connect to the server */
if (!smtp.connect(&config))
{
ESP_MAIL_PRINTF("Connection error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
return;
}
if (!smtp.isLoggedIn())
{
Serial.println("\nNot yet logged in.");
}
else
{
if (smtp.isAuthenticated())
Serial.println("\nSuccessfully logged in.");
else
Serial.println("\nConnected with no Auth.");
}
// **This is where I have tried to insert my code**
// Time between salt level checks is 15 minutes unless Test switch is set to "Test" position, in which case the time between level checks is 1 second
testState = digitalRead(testPin); //get the state of the test switch. If set to "Test", testState will be set to LOW
if (testState == LOW) //i.e. the test switch is set to "Test'
{
// Function to read data from the ultrasonic sensor
float readSensorData()
{
// Trigger a low signal before sending a high signal
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Send a 10-microsecond high signal to the trigPin
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
// Return to low signal
digitalWrite(trigPin, LOW);
// Measure the duration of the high signal on the echoPin
unsigned long microsecond = pulseIn(echoPin, HIGH);
// Calculate the distance using the speed of sound (29.00µs per centimeter, and need to divide by 2 because the signal is travelling to AND from the object)
float distance = microsecond / 29.00 / 2;
// Return the calculated distance
return distance;
}
float distance = readSensorData();
Serial.print(distance);
Serial.print(" cm. Test state should be 0 = ");
Serial.println(testState);
if (distance>25) // distance from the ultrasonic unit to the top of the salt level should be 25 cm or less
{
digitalWrite(buzzerPin, HIGH);//turn on the buzzer
delay(1000); //keep the buzzer on for 1 second
digitalWrite(buzzerPin, LOW); //turn off buzzer
} else
{ delay(1000);
digitalWrite(buzzerPin, LOW);
}
} else
{
// test state must be HIGH - i.e. the Test switch is NOT turned on, so do the normal operation of testing salt level every 15 minutes
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval)
{ // if 15 minutes have elapsed, then...
// save the last time you tested the salt level
previousMillis = currentMillis;
// Read distance from the ultrasonic sensor
float distance = readSensorData();
// Print the measured distance to the serial monitor. These print statements are only used to test and debug the programme
Serial.print(distance);
Serial.print(" cm. Test state should be 1. Test state = ");
Serial.println(testState); //must print 1 for HIGH
if (distance>25)
{
digitalWrite(buzzerPin, HIGH);//turn on the buzzer
delay(10000); //keep the buzzer on for 10 seconds
digitalWrite(buzzerPin, LOW); //turn off buzzer
/* Start sending Email and close the session */
SMTP_Message message;
if (!MailClient.sendMail(&smtp, &message))
ESP_MAIL_PRINTF("Error, Status Code: %d, Error Code: %d, Reason: %s", smtp.statusCode(), smtp.errorCode(), smtp.errorReason().c_str());
}
else
{
digitalWrite(buzzerPin, LOW);
}
} else {}
}
}//end loop
/* Callback function to get the Email sending status */
void smtpCallback(SMTP_Status status){
/* Print the current status */
Serial.println(status.info());
/* Print the sending result */
if (status.success()){
// ESP_MAIL_PRINTF used in the examples is for format printing via debug Serial port
// that works for all supported Arduino platform SDKs e.g. AVR, SAMD, ESP32 and ESP8266.
// In ESP8266 and ESP32, you can use Serial.printf directly.
Serial.println("----------------");
ESP_MAIL_PRINTF("Message sent success: %d\n", status.completedCount());
ESP_MAIL_PRINTF("Message sent failed: %d\n", status.failedCount());
Serial.println("----------------\n");
for (size_t i = 0; i < smtp.sendingResult.size(); i++)
{
/* Get the result item */
SMTP_Result result = smtp.sendingResult.getItem(i);
ESP_MAIL_PRINTF("Message No: %d\n", i + 1);
ESP_MAIL_PRINTF("Status: %s\n", result.completed ? "success" : "failed");
ESP_MAIL_PRINTF("Date/Time: %s\n", MailClient.Time.getDateTimeString(result.timestamp, "%B %d, %Y %H:%M:%S").c_str());//month, day of month, Year, Hours
//Minutes, Seconds
ESP_MAIL_PRINTF("Recipient: %s\n", result.recipients.c_str());
ESP_MAIL_PRINTF("Subject: %s\n", result.subject.c_str());
}
Serial.println("----------------\n");
// You need to clear sending result as the memory usage will grow up.
smtp.sendingResult.clear();
}
}