User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Automated email send out on event not working

Mon Sep 27, 2021 8:11 pm

So this week I decided to try something new which was an automated email notification when some chilli plants I am growing need watering.

I used the tutorial from here: https://thepihut.com/blogs/raspberry-pi ... n-tutorial

downloaded the files and then altered the code accordingly with my email credentials, however I have essentially put in a name over the actual in the below code for security :)

Code: Select all

#!/usr/bin/python

# Start by importing the libraries we want to use

import RPi.GPIO as GPIO # This is the GPIO library we need to use the GPIO pins on the Raspberry Pi
import smtplib # This is the SMTP library we need to send the email notification
import time # This is the time library, we need this so we can use the sleep function

# Define some variables to be used later on in our script

# You might not need the username and password variable, depends if you are using a provider or if you have your raspberry pi setup to send emails
# If you have setup your raspberry pi to send emails, then you will probably want to use 'localhost' for your smtp_host

smtp_username = "mysendemailaddress@gmail.com" # This is the username used to login to your SMTP provider
smtp_password = "password" # This is the password used to login to your SMTP provider
smtp_host = "smtp.gmail.com" # This is the host of the SMTP provider
smtp_port = 587 # This is the port that your SMTP provider uses

smtp_sender = "mysendemailaddress@gmail.com" # This is the FROM email address
smtp_receivers = ['mypersonalemail@hotmail.com'] # This is the TO email address

# The next two variables use triple quotes, these allow us to preserve the line breaks in the string.

# This is the message that will be sent when NO moisture is detected

message_dead = """From: The Right Chilli <mysendemailaddress@gmail.com>
To: Receiver Name <mypersonalemail@hotmail.com>
Subject: Moisture Sensor Notification

Warning, no moisture detected! Plant death imminent!!! :'(
"""

# This is the message that will be sent when moisture IS detected again

message_alive = """From: The Right Chilli <mysendemailaddress@gmail.com>
To: Receiver Name <mypersonalemail@hotmail.com>
Subject: Moisture Sensor Notification

Panic over! Plant has water again :)
"""

# This is our sendEmail function

def sendEmail(smtp_message):
        try:
                smtpObj = smtplib.SMTP(smtp_host, smtp_port)
                smtpObj.login(smtp_username, smtp_password) # If you don't need to login to your smtp provider, simply remove this line
                smtpObj.sendmail(smtp_sender, smtp_receivers, smtp_message)
                print "Successfully sent email"
        except smtplib.SMTPException:
                print "Error: unable to send email"

# This is our callback function, this function will be called every time there is a change on the specified GPIO channel, in this example we are using 17

def callback(channel):
        if GPIO.input(channel):
         print "LED off"
                sendEmail(message_dead)
        else:
                print "LED on"
                sendEmail(message_alive)

# Set our GPIO numbering to BCM
GPIO.setmode(GPIO.BCM)

# Define the GPIO pin that we have our digital output from our sensor connected to
channel = 17
# Set the GPIO pin to an input
GPIO.setup(channel, GPIO.IN)

# This line tells our script to keep an eye on our gpio pin and let us know when the pin goes HIGH or LOW
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=300)
# This line asigns a function to the GPIO pin so that when the above line tells us there is a change on the pin, run this function
GPIO.add_event_callback(channel, callback)

# This is an infinte loop to keep our script running
while True:
        # This line simply tells our script to wait 0.1 of a second, this is so the script doesnt hog all of the CPU
        time.sleep(0.1)

Now when I run the code it sits with nothing, if I trigger a response on the moisture sensor I get this:
LED on
Error: unable to send email
LED off
Error: unable to send email
I wonder if anyone could see anything obvious with the syntax or something i should have changed, or if there might be other protocols I need to enable on my raspberry pi?

Its on a Raspberry Pi Zero, USB wifi dongle, a May 2021 version of Raspbian installed (think thats the latest one) I did an update too.

I'm fairly new to coding, so just getting tutorials to work is a big step for me!

ame
Posts: 3713
Joined: Sat Aug 18, 2012 1:21 am
Location: New Zealand

Re: Automated email send out on event not working

Mon Sep 27, 2021 8:43 pm

Edit this function:

Code: Select all

def sendEmail(smtp_message):
        try:
                smtpObj = smtplib.SMTP(smtp_host, smtp_port)
                smtpObj.login(smtp_username, smtp_password) # If you don't need to login to your smtp provider, simply remove this line
                smtpObj.sendmail(smtp_sender, smtp_receivers, smtp_message)
                print "Successfully sent email"
        except smtplib.SMTPException:
                print "Error: unable to send email"
To this:

Code: Select all

def sendEmail(smtp_message):
                smtpObj = smtplib.SMTP(smtp_host, smtp_port)
                smtpObj.login(smtp_username, smtp_password) # If you don't need to login to your smtp provider, simply remove this line
                smtpObj.sendmail(smtp_sender, smtp_receivers, smtp_message)
                print "Successfully sent email"
You might have to fix the indentation too.

Basically, the try...except clause will exit if there are any errors, but won't print the actual error, but also, won't exit the program.

If you take away the try...except clause and run it again your program will crash and display an error message.

Alternatively, you can print the error in the except clause:

Code: Select all

def sendEmail(smtp_message):
        try:
                smtpObj = smtplib.SMTP(smtp_host, smtp_port)
                smtpObj.login(smtp_username, smtp_password) # If you don't need to login to your smtp provider, simply remove this line
                smtpObj.sendmail(smtp_sender, smtp_receivers, smtp_message)
                print "Successfully sent email"
        except smtplib.SMTPException as e:
                print(e)
                print "Error: unable to send email"
Incidentally, you don't seem to be using python 3. If you are just starting out I suggest you focus solely on python 3.

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Tue Sep 28, 2021 6:40 pm

Ok so I tried the first option and just hashed out the code you suggested:

Code: Select all

def sendEmail(smtp_message):
#       try:
                smtpObj = smtplib.SMTP(smtp_host, smtp_port)
                smtpObj.login(smtp_username, smtp_password) # If you don't need to login to your smtp provider, simply remove this line
                smtpObj.sendmail(smtp_sender, smtp_receivers, smtp_message)
                print "Successfully sent email"
#       except smtplib.SMTPException:
#               print "Error: unable to send email"

# This is our callback function, this function will be called every time there is a change on the specified GPIO channel, in this example we are using 17

def callback(channel):
When I ran the code and triggered the email response this is what came back:
LED off
Traceback (most recent call last):
File "moisture2.py", line 58, in callback
sendEmail(message_dead)
File "moisture2.py", line 47, in sendEmail
smtpObj.login(smtp_username, smtp_password) # If you don't need to login to your smtp provider, simply remove this line
File "/usr/lib/python2.7/smtplib.py", line 586, in login
raise SMTPException("SMTP AUTH extension not supported by server.")
smtplib.SMTPException: SMTP AUTH extension not supported by server.
LED on
Traceback (most recent call last):
File "moisture2.py", line 61, in callback
sendEmail(message_alive)
File "moisture2.py", line 47, in sendEmail
smtpObj.login(smtp_username, smtp_password) # If you don't need to login to your smtp provider, simply remove this line
File "/usr/lib/python2.7/smtplib.py", line 586, in login
raise SMTPException("SMTP AUTH extension not supported by server.")
smtplib.SMTPException: SMTP AUTH extension not supported by server.
So it would seem like this suggests the problem is with the way that mail is actually handled?

I tried changing the email address to a spare hotmail one I have and with hotmail there is TLS and non TLS supported port numbers, tried both and each time got the same message as above.

ame
Posts: 3713
Joined: Sat Aug 18, 2012 1:21 am
Location: New Zealand

Re: Automated email send out on event not working

Tue Sep 28, 2021 8:05 pm

Not sure what the problem might be, but the error messages should guide you (now that you can see them).

If I google the actual error message I find this:
https://stackoverflow.com/questions/372 ... -by-server

Does that help?

And again, you should move up to Python 3.

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Tue Sep 28, 2021 9:19 pm

I think I came across that link you provided while trying to do my own searches, but what I was confused by is the different format of how people were trying to send mail.

Also whats the advantage of python3?

I tried running that same file in python3 and get this error now:
File "moisture2.py", line 49
print "Successfully sent email"
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Successfully sent email")?
so I dont see how that really helps things as I assume the original program was written with the standard python 2.7?

ame
Posts: 3713
Joined: Sat Aug 18, 2012 1:21 am
Location: New Zealand

Re: Automated email send out on event not working

Tue Sep 28, 2021 9:31 pm

Python 3 is the latest version. All new development will occur with Python 3. Python 2 is essentially end-of-life.

Since you are new to coding then you will have no baggage with you, so you can go straight into Python 3 and not care about the previous version.

And, as you have discovered, the Python 3 syntax for certain functions (such as print) is different. Also, libraries and other support functions that you may have installed for Python 2 are not accessible to Python 3, so you'll have to install the Python 3 versions of the things you need.

Fundamentally the version doesn't matter, nor does the language. You are solving a problem, which requires certain actions in a certain order. Once you know the steps then it's just a case of implementation in your favourite language.

Sending email is a very typical requirement for a lot of projects. I really recommend you find an example using Python 3 (which will undoubtedly look the same as the Python 2 example, but perhaps with slightly different syntax). Then focus on the error message, which will probably be specific to your ISP or your account.

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Tue Sep 28, 2021 9:43 pm

ame wrote:
Tue Sep 28, 2021 9:31 pm
Python 3 is the latest version. All new development will occur with Python 3. Python 2 is essentially end-of-life.

Since you are new to coding then you will have no baggage with you, so you can go straight into Python 3 and not care about the previous version.

And, as you have discovered, the Python 3 syntax for certain functions (such as print) is different. Also, libraries and other support functions that you may have installed for Python 2 are not accessible to Python 3, so you'll have to install the Python 3 versions of the things you need.

Fundamentally the version doesn't matter, nor does the language. You are solving a problem, which requires certain actions in a certain order. Once you know the steps then it's just a case of implementation in your favourite language.

Sending email is a very typical requirement for a lot of projects. I really recommend you find an example using Python 3 (which will undoubtedly look the same as the Python 2 example, but perhaps with slightly different syntax). Then focus on the error message, which will probably be specific to your ISP or your account.
OK that makes sense, I have started having a fiddle about with the way that the mail is dealt with or called for, thats what confused me and I had different errors of syntax, for python 3, but with 2.7 no error came back, equally no mail has appeared soooooo back to square one.

I think you are right I need to sit down and analyse how things are done different and rewrite the code to work with the newer python. Email notification is going to be key as I think once I get it to work I'm going to end up using it alot for notifications of various projects!

User avatar
rpdom
Posts: 19126
Joined: Sun May 06, 2012 5:17 am
Location: Chelmsford, Essex, UK

Re: Automated email send out on event not working

Wed Sep 29, 2021 7:03 am

ame wrote:
Tue Sep 28, 2021 9:31 pm
Python 3 is the latest version. All new development will occur with Python 3. Python 2 is essentially end-of-life.
Also, when the Bullseye version of Raspberry Pi OS based on Debian 11 is released, it won't have Python 2.

That will probably happen fairly soon. It is being worked on now.
Unreadable squiggle

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Wed Sep 29, 2021 8:10 am

Seeing as you are using gmail as the account to send from , have you selected " allow less secure apps " on the account in question ?

I always suggest you set up a separate account for use with your pi because of this.

and follow these simple rules

1. only use A-Z, a-z, 0-9 and the full stop in the account name and letters and numbers only in the password.
2. enable allow less secure apps on the account
3.use the code below to send a mail, it will probably fail the first time , so log in to the account via your browser and look for a security message from google , you will probably have to tell them the pi is your device, once done try sending mail again.

test code to send message.

Code: Select all

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

email_user = "account@gmail.com"
email_password = "password"
email_send = "address to send to"

subject = "Test email from pi"

msg = MIMEMultipart()
msg["From"] = email_user
msg["To"] = email_send
msg["Subject"] = subject

body = "Hi there, sending this email from Python!"
msg.attach(MIMEText(body,"plain"))

text = msg.as_string()
server = smtplib.SMTP("smtp.gmail.com",587)
server.starttls()
server.login(email_user,email_password)


server.sendmail(email_user,email_send,text)
server.quit()
code is tested and known to work if account is set up correctly.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Wed Sep 29, 2021 12:36 pm

pcmanbob wrote:
Wed Sep 29, 2021 8:10 am
Seeing as you are using gmail as the account to send from , have you selected " allow less secure apps " on the account in question ?

I always suggest you set up a separate account for use with your pi because of this.

and follow these simple rules

1. only use A-Z, a-z, 0-9 and the full stop in the account name and letters and numbers only in the password.
2. enable allow less secure apps on the account
3.use the code below to send a mail, it will probably fail the first time , so log in to the account via your browser and look for a security message from google , you will probably have to tell them the pi is your device, once done try sending mail again.

test code to send message.

Code: Select all

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

email_user = "account@gmail.com"
email_password = "password"
email_send = "address to send to"

subject = "Test email from pi"

msg = MIMEMultipart()
msg["From"] = email_user
msg["To"] = email_send
msg["Subject"] = subject

body = "Hi there, sending this email from Python!"
msg.attach(MIMEText(body,"plain"))

text = msg.as_string()
server = smtplib.SMTP("smtp.gmail.com",587)
server.starttls()
server.login(email_user,email_password)


server.sendmail(email_user,email_send,text)
server.quit()
code is tested and known to work if account is set up correctly.
I'll have to try the code tonight if I get chance.

I have enabled the use of less secure apps as one of the first things I did when I went over to a gmail account. I had been using a hotmail email account, however neither of which worked and I always got thee same results.

When I was doing motion notifications with motioneyeos on my raspberry pi camera, I found that hotmail just worked out the box, so I started with that same account when doing my moisture monitor only it wouldnt send an email.

One query I do have is if that code does work, how I swap that bit in to my code? Would it be something like this:

Code: Select all

#!/usr/bin/python

# Start by importing the libraries we want to use

import RPi.GPIO as GPIO # This is the GPIO library we need to use the GPIO pins on the Raspberry Pi
import smtplib # This is the SMTP library we need to send the email notification
import time # This is the time library, we need this so we can use the sleep function
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# Define some variables to be used later on in our script

# You might not need the username and password variable, depends if you are using a provider or if you have your raspberry pi setup to send emails
# If you have setup your raspberry pi to send emails, then you will probably want to use 'localhost' for your smtp_host

email_user = "account@gmail.com"
email_password = "password"
email_send = "address@hotmail.com"

# The next two variables use triple quotes, these allow us to preserve the line breaks in the string.

# This is the message that will be sent when NO moisture is detected

message_dead =
             msg = MIMEMultipart()
             msg["From"] = email_user
             msg["To"] = email_send
             msg["Subject"] = subject
             subject = "Moisture Change Alert"
             body = "Hi there, Your plants need watering, send help!!"
             msg.attach(MIMEText(body,"plain"))
             text = msg.as_string()

# This is the message that will be sent when moisture IS detected again


message_alive =
             msg = MIMEMultipart()
             msg["From"] = email_user
             msg["To"] = email_send
             msg["Subject"] = subject
             subject = "Moisture Change Alert"
             body = "Hi there, Your plant has water again, happy times!!"
             msg.attach(MIMEText(body,"plain"))
             text = msg.as_string()

# This is our sendEmail function

def sendEmail(smtp_message):
        try:            
            server = smtplib.SMTP("smtp.gmail.com",587)
            server.starttls()
            server.login(email_user,email_password)
            server.sendmail(email_user,email_send,text)
            server.quit() 
                print "Successfully sent email"
        except smtplib.SMTPException:
                print "Error: unable to send email"

# This is our callback function, this function will be called every time there is a change on the specified GPIO channel, in this example we are using 17

def callback(channel):
        if GPIO.input(channel):
         print "LED off"
                sendEmail(message_dead)
        else:
                print "LED on"
                sendEmail(message_alive)

# Set our GPIO numbering to BCM
GPIO.setmode(GPIO.BCM)

# Define the GPIO pin that we have our digital output from our sensor connected to
channel = 17
# Set the GPIO pin to an input
GPIO.setup(channel, GPIO.IN)

# This line tells our script to keep an eye on our gpio pin and let us know when the pin goes HIGH or LOW
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=300)
# This line asigns a function to the GPIO pin so that when the above line tells us there is a change on the pin, run this function
GPIO.add_event_callback(channel, callback)

# This is an infinte loop to keep our script running
while True:
        # This line simply tells our script to wait 0.1 of a second, this is so the script doesnt hog all of the CPU
        time.sleep(0.1)
obviously I have no real idea what I am doing, just using what I perceive to be the way it should work, I sometimes dont see how on earth coding is logical!

Later I want to add a second channel, at the end of the code there is this bit:
# Define the GPIO pin that we have our digital output from our sensor connected to
channel = 17
# Set the GPIO pin to an input
GPIO.setup(channel, GPIO.IN)

# This line tells our script to keep an eye on our gpio pin and let us know when the pin goes HIGH or LOW
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=300)
# This line asigns a function to the GPIO pin so that when the above line tells us there is a change on the pin, run this function
GPIO.add_event_callback(channel, callback)
Do I just change 'Channel = 17' to 'Channel = 17, 18' as I have hooked up a second monitor to gpio 18?

Thanks again for giving me some insight :)

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Wed Sep 29, 2021 12:48 pm

If you get your email working first then I will help you set up your code using my example code to do the actual sending.

Yes you just need to set up the gpio pin in the same way, but you will have to change the call back name if you want it to run a different function.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Wed Sep 29, 2021 7:13 pm

pcmanbob wrote:
Wed Sep 29, 2021 12:48 pm
If you get your email working first then I will help you set up your code using my example code to do the actual sending.

Yes you just need to set up the gpio pin in the same way, but you will have to change the call back name if you want it to run a different function.
So the good news is, the basic email works!

Now I just have to understand the rest :oops:

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Wed Sep 29, 2021 7:37 pm

bugsy_malone 666 wrote:
Wed Sep 29, 2021 7:13 pm
pcmanbob wrote:
Wed Sep 29, 2021 12:48 pm
If you get your email working first then I will help you set up your code using my example code to do the actual sending.

Yes you just need to set up the gpio pin in the same way, but you will have to change the call back name if you want it to run a different function.
So the good news is, the basic email works!

Now I just have to understand the rest :oops:
That's good news , I will have a look at you code tomorrow afternoon hopefully and try and post some example code.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Wed Sep 29, 2021 9:35 pm

pcmanbob wrote:
Wed Sep 29, 2021 7:37 pm
bugsy_malone 666 wrote:
Wed Sep 29, 2021 7:13 pm
pcmanbob wrote:
Wed Sep 29, 2021 12:48 pm
If you get your email working first then I will help you set up your code using my example code to do the actual sending.

Yes you just need to set up the gpio pin in the same way, but you will have to change the call back name if you want it to run a different function.
So the good news is, the basic email works!

Now I just have to understand the rest :oops:
That's good news , I will have a look at you code tomorrow afternoon hopefully and try and post some example code.
I'm going to apologize for not searching hard enough, it seems you have solved this problem for someone else back in Feb 2020! So I had a look at the code you had written then and coded in to what I have, however I have found a problem that I am not sure about. Heres the code:

Code: Select all

#!/usr/bin/python

# Start by importing the libraries we want to use

import RPi.GPIO as GPIO # This is the GPIO library we need to use the GPIO pins on the Raspberry Pi
import smtplib # This is the SMTP library we need to send the email notification
import time # This is the time library, we need this so we can use the sleep function
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# Define some variables to be used later on in our script

# You might not need the username and password variable, depends if you are using a provider or if you have your raspberry pi setup to send emails
# If you have setup your raspberry pi to send emails, then you will probably want to use 'localhost' for your smtp_host


# The next two variables use triple quotes, these allow us to preserve the line breaks in the string.

# This is the message that will be sent when NO moisture is detected


# This is our sendEmail function

def send_mail(body):
            email_user = "comingfrom@gmail.com"
            email_password = "password"
            email_send = “going to@hotmail.com"

            subject = "Moisture Sensor Notification"

            msg = MIMEMultipart()
            msg["From"] = email_user
            msg["To"] = email_send
            msg["Subject"] = subject

            msg.attach(MIMEText(body,"plain"))

            text = msg.as_string()
            server = smtplib.SMTP("smtp.gmail.com",587)
            server.starttls()
            server.login(email_user,email_password)

            server.sendmail(email_user,email_send,text)
            server.quit()

# This is our callback function, this function will be called every time there is a change on the specified GPIO channel, in this example we are using 17

def callback(channel):
        if GPIO.input(channel):
                print("LED off")
                body = "Help Moisture level low or not detected! Water Required! I feel death is near :("
                send_mail(body) #(message_dead)
                       
        else:
                print("LED on")
                body = "Panic over! I have been watered, I feel alive! :)"
                send_mail(body)

# Set our GPIO numbering to BCM
GPIO.setmode(GPIO.BCM)

# Define the GPIO pin that we have our digital output from our sensor connected to
channel = 17
# Set the GPIO pin to an input
GPIO.setup(channel, GPIO.IN)

# This line tells our script to keep an eye on our gpio pin and let us know when the pin goes HIGH or LOW
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=300)
# This line asigns a function to the GPIO pin so that when the above line tells us there is a change on the pin, run this function
GPIO.add_event_callback(channel, callback)

# This is an infinte loop to keep our script running
while True:
        # This line simply tells our script to wait 0.1 of a second, this is so the script doesnt hog all of the CPU
        time.sleep(1)

Now initially it worked like a charm, except it was constantly sending me emails for 'on' every minute. I realise I have gotten the time set to 1 second ( I know the hash text says otherwise, I changed the time), I guess the bit I want to understand now is how it checks a change in state against its previous state, if there is not change it doesnt send a new email. I guess another alternative would be to set time to 86400 which is 24 hours so I only get one email per day maybe?

I appreciate the help greatly :)

I would in the future like to add a second channel, so it checks the state of either and if either of them are flag it sends the email. Better still would be to tell me which one! I also want to add basic temperature monitoring (I have played with DHT11/22 sensors before) so it sends an email and tells me the current situation at the same time, then maybe a twitter photo, so many ideas so much to learn!
Last edited by bugsy_malone 666 on Thu Sep 30, 2021 7:19 pm, edited 1 time in total.

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Thu Sep 30, 2021 7:05 am

I suggest you edit your posted code and remove the usernames and password .
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Thu Sep 30, 2021 8:35 am

So I edited your code and added some simple logic to check if the mail has been sent and prevents resending if it has,

I also added the call back to your GPIO.add_event_detect line.

As your while true loop is only keeping the program running you can set a much longer sleep as it has no affect on your gpio event or the call back.

Code: Select all

#!/usr/bin/python

# Start by importing the libraries we want to use

import RPi.GPIO as GPIO # This is the GPIO library we need to use the GPIO pins on the Raspberry Pi
import smtplib # This is the SMTP library we need to send the email notification
import time # This is the time library, we need this so we can use the sleep function
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

# Define some variables to be used later on in our script

mcheck1 = 0
mcheck2 = 0

# You might not need the username and password variable, depends if you are using a provider or if you have your raspberry pi setup to send emails
# If you have setup your raspberry pi to send emails, then you will probably want to use 'localhost' for your smtp_host


# The next two variables use triple quotes, these allow us to preserve the line breaks in the string.

# This is the message that will be sent when NO moisture is detected


# This is our sendEmail function

def send_mail(body):
            email_user = "xxxxxxxxxxxx@gmail.com"
            email_password = "password"
            email_send = "xxxxxxxxxx@hotmail.com"

            subject = "Moisture Sensor Notification"

            msg = MIMEMultipart()
            msg["From"] = email_user
            msg["To"] = email_send
            msg["Subject"] = subject

            msg.attach(MIMEText(body,"plain"))

            text = msg.as_string()
            server = smtplib.SMTP("smtp.gmail.com",587)
            server.starttls()
            server.login(email_user,email_password)

            server.sendmail(email_user,email_send,text)
            server.quit()

# This is our callback function, this function will be called every time there is a change on the specified GPIO channel, in this example we are using 17

def callback(channel):
        global mcheck1,mcheck2
        if GPIO.input(channel):
            if mcheck1 == 0:
                print("LED off")
                body = "Help Moisture level low or not detected! Water Required! I feel death is near :("
                send_mail(body) #(message_dead)
                mcheck1 = 1
                mcheck2 = 0
                       
        else:
            if mcheck2 == 0:    
                print("LED on")
                body = "Panic over! I have been watered, I feel alive! :)"
                send_mail(body)
                mcheck2 = 1
                mcheck1 = 0

# Set our GPIO numbering to BCM
GPIO.setmode(GPIO.BCM)

# Define the GPIO pin that we have our digital output from our sensor connected to
channel = 17
# Set the GPIO pin to an input
GPIO.setup(channel, GPIO.IN)

# This line tells our script to keep an eye on our gpio pin and let us know when the pin goes HIGH or LOW
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=300, callback=callback)
# This line asigns a function to the GPIO pin so that when the above line tells us there is a change on the pin, run this function
#GPIO.add_event_callback(channel, callback) added the call back to the above setup line for the gpio pin event

# This is an infinte loop to keep our script running
while True:
        # This line simply tells our script to wait 0.1 of a second, this is so the script doesnt hog all of the CPU
        time.sleep(10)

this is untested code so there may be errors.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Thu Sep 30, 2021 7:20 pm

pcmanbob wrote:
Thu Sep 30, 2021 7:05 am
I suggest you edit your posted code and remove the usernames and password .
I did that on all the rest, I thought I’d done it on this one, I’ve changed it now thought!

Yesterday was a bit of a long day.

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Sat Oct 09, 2021 6:39 pm

So I thought I’d come back and say thanks for the help, it’s been working ok now for a week, the only issue I do get is at the point where it detects moisture change drying out, I get about 30 emails! When I water it, I only get one.

I appreciate the help a lot as it’s now so,etching that works and does it’s job telling me every few days it needs watering :)

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Sat Oct 09, 2021 7:14 pm

It sounds like the part of the program that detects it's dry is being trigger then being triggered again.

Over what sort of time period do you get the emails.

When I get a spare 5 min and my bench is clear I will try and set up a pi to test the program.

edit..
Looking at the code again , you don't have a pull up/down on your input pin so does your moisture detector output both a high and a low signal ?

A link to the moisture detect you are using might help too.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Sun Oct 10, 2021 8:26 am

So I ran the code I posted above
pcmanbob wrote:
Thu Sep 30, 2021 8:35 am
I used a simple wire loop switching gpio between high and low and apart from the very first trigger were I got both emails, it worked correctly from then on ,

I only ever got one email either wet or dry.

The only way I got get lots of emails was to constantly disconnect and reconnect the gpio pin to ground which then resulted in both wet and dry emails repeating, This might be what's happening if your moisture detector is changing form high to low very quickly when it just about reaches the dry point.

To try and limit this I have added a couple of lines to the code that will delay the sending of the dry mail for 30 seconds to check if its still dry, this might help. if you still get a number of messages then try increasing the time by 30 seconds.

If this works then we know the problem is as I suspected and I will change the code to take this in to account by adding a dry counter.

So please try the test code below and let me know the results

Code: Select all

#!/usr/bin/python3

# Start by importing the libraries we want to use

import RPi.GPIO as GPIO # This is the GPIO library we need to use the GPIO pins on the Raspberry Pi
import smtplib # This is the SMTP library we need to send the email notification
import time # This is the time library, we need this so we can use the sleep function
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase


# Define some variables to be used later on in our script

mcheck1 = 0
mcheck2 = 0

# You might not need the username and password variable, depends if you are using a provider or if you have your raspberry pi setup to send emails
# If you have setup your raspberry pi to send emails, then you will probably want to use 'localhost' for your smtp_host


# The next two variables use triple quotes, these allow us to preserve the line breaks in the string.

# This is the message that will be sent when NO moisture is detected


# This is our sendEmail function

def send_mail(body):
            email_user = "xxxxxxxxxxxx@gmail.com"
            email_password = "password"
            email_send = "xxxxxxxxxx@hotmail.com"

            subject = "Moisture Sensor Notification"

            msg = MIMEMultipart()
            msg["From"] = email_user
            msg["To"] = email_send
            msg["Subject"] = subject

            msg.attach(MIMEText(body,"plain"))

            text = msg.as_string()
            server = smtplib.SMTP("smtp.gmail.com",587)
            server.starttls()
            server.login(email_user,email_password)

            server.sendmail(email_user,email_send,text)
            server.quit()

# This is our callback function, this function will be called every time there is a change on the specified GPIO channel, in this example we are using 17

def callback(channel):
        global mcheck1,mcheck2
        if GPIO.input(channel):
            time.sleep(30)          # increase this time by 30 seconds if you still get more than 1 dry email.
            if GPIO.input(channel):
                if mcheck1 == 0:
                    print("LED off")
                    body = "Help Moisture level low or not detected! Water Required! I feel death is near :("
                    send_mail(body) #(message_dead)
                    mcheck1 = 1
                    mcheck2 = 0
                
                       
        else:
            if mcheck2 == 0:    
                print("LED on")
                body = "Panic over! I have been watered, I feel alive! :)"
                send_mail(body)
                mcheck2 = 1
                mcheck1 = 0

# Set our GPIO numbering to BCM
GPIO.setmode(GPIO.BCM)

# Define the GPIO pin that we have our digital output from our sensor connected to
channel = 17
# Set the GPIO pin to an input
GPIO.setup(channel, GPIO.IN)

# This line tells our script to keep an eye on our gpio pin and let us know when the pin goes HIGH or LOW
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=300, callback=callback)
# This line asigns a function to the GPIO pin so that when the above line tells us there is a change on the pin, run this function
#GPIO.add_event_callback(channel, callback) added the call back to the above setup line for the gpio pin event

# This is an infinte loop to keep our script running
while True:
        # This line simply tells our script to wait 0.1 of a second, this is so the script doesnt hog all of the CPU
        time.sleep(10)
        
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Mon Oct 11, 2021 8:42 am

Hi dude, I have a suspicion as to what part of my problem might be, it could be degradation the sensors and the fact they are on and off variety.

I got them from Amazon, https://www.amazon.co.uk/AZDelivery-Hyg ... s=1&sr=8-3 because they were cheap for 3 to try this project out, but I have found they have degraded pretty quickly in about 3-4 weeks and thats where I think some of the email response problem lies.

From what I gathered with the pin High/Low setup, the Raspberry pi watches to see which way it goes, its right near the bottom of the code

Code: Select all

# This line tells our script to keep an eye on our gpio pin and let us know when the pin goes HIGH or LOW
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=300, callback=callback)
Also a little after that it has:

Code: Select all

# This is an infinte loop to keep our script running
while True:
        # This line simply tells our script to wait 10 seconds, this is so the script doesnt hog all of the CPU
        time.sleep(10)
Thats at the very bottom, so surely if I ramp that up to about 300 will mean the script only runs once every 5 minutes meaning it only does its check every 5 minutes?

Something I am going to try this week is adding in some transistor control (something I have managed before with success for turning power on at certain times in another project)for power to the sensors, I think continuous power is why they are degrading so quickly, potentially that may sort out the false triggers on the email too. Just waiting for a Proto board to turn up and got to see when I get home if I have any NPN transistors laying about. I was thinking in that instance if I use Transistors to power up the sensors, I could have a python program that just does that, runs at a set interval using Crontab, coupled with then running this moisture sensor program with crontab at set times also, so essentially it only does something maybe 4 times a day, reducing problems with too many emails also.

I have also fiddled with another python program to take twitter photos and use Crontab to trigger the program running a couple of times a day, as far as I can tell its not worked this morning, but I can make it work and send a photo to twitter if I run the program through terminal. I have used Crontab before and it worked ok on a different project, but it has been a while.

Its quite ambitious little project so I appreciate all the help I can get :)

pcmanbob
Posts: 11783
Joined: Fri May 31, 2013 9:28 pm
Location: Mansfield UK

Re: Automated email send out on event not working

Mon Oct 11, 2021 8:50 am

So changing the time sleep at the bottom of the program will make no difference , all it does is keep the program running , you can set any time you like and it will not change how the program runs, because you are using event detect to trigger the sending of mail.

So as soon as an even is detected it will send a mail, regardless of the sleep at the end of the code.

Did you try the new code I posted ?

I have added a sleep delay in the function that makes the code wait 30 seconds and then it checks again to see if input is still high this might help.
We want information… information… information........................no information no help
The use of crystal balls & mind reading are not supported

ame
Posts: 3713
Joined: Sat Aug 18, 2012 1:21 am
Location: New Zealand

Re: Automated email send out on event not working

Mon Oct 11, 2021 9:04 am

Sorry, those sensors are rubbish, and they basically corrode away very quickly.

You should have more success with a capacitive sensor, but they all suffer due to exposure to the elements.

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Mon Oct 11, 2021 10:08 am

pcmanbob wrote:
Mon Oct 11, 2021 8:50 am
So changing the time sleep at the bottom of the program will make no difference , all it does is keep the program running , you can set any time you like and it will not change how the program runs, because you are using event detect to trigger the sending of mail.

So as soon as an even is detected it will send a mail, regardless of the sleep at the end of the code.

Did you try the new code I posted ?

I have added a sleep delay in the function that makes the code wait 30 seconds and then it checks again to see if input is still high this might help.
Havent had chance to test the code because I only saw it first thing this morning when I got to work, so wont be able to get to it until tonight if I have time.

Looking at how the emails seem to come in, its about 3-4 in the period of a minute, followed by maybe a minute-3 minutes before another batch, I'll get this for up to 10 minutes before the state actually changes to a definite.

I know the sensor arent exactly the greatest, but for the base of getting this project to work, for their cost its somewhere to start! I was looking in to what else I can use for sensors, I have wondered if stainless steel wire might work well enough, I have seen someone use graphite pencil leads as a long term solution, I guess it depends on resistance scales, the boards to have adjustment at least.

User avatar
bugsy_malone 666
Posts: 305
Joined: Mon Dec 17, 2012 10:50 pm
Location: Basingstoke UK

Re: Automated email send out on event not working

Sun Oct 17, 2021 3:34 pm

ame wrote:
Mon Oct 11, 2021 9:04 am
Sorry, those sensors are rubbish, and they basically corrode away very quickly.

You should have more success with a capacitive sensor, but they all suffer due to exposure to the elements.
Yeah I learned that pretty quickly, after looking around on the internet it seems the answer is to change the bit thats inserted in to the soil to carbon graphite rods, so thats what I have now as apparently they are non toxic and last a very long time.

Havent done any real long term testing yet as something I am looking at is the fact they also corrode through the constant power through them, so the next step is to have power control. I have achieved what I want with a basic little script and a BC548 Transistor, that turns the sensors power on, whats 5 minutes then turns it off again. I can activate this with a crontab job to allow it on a set times of day, meaning that its not permanently powered.

Now the next problem I encountered here is the fact that then sends me an email because its a triggered change of event.

So I thought maybe the next step would be to get it so Crontab triggers my transistor power, then triggers my moisture detector to run just once, but it needs to know the state change from the previous check. I wanted to get this to happen once everyday at maybe 10pm, as theres no sun to influence the conditions.

Return to “Automation, sensing and robotics”