Have you felt the need to be notified by your Rasp when something is happening in your home (and not only)?
Well, I certainly did. I always forgot a lot of things that can be friendly reminded. Like watering the plants, closing the door, leaving the light open, although I don't have a cat or dog, I would definitely have needed to know if they are low on food or water. (and many other situations)
If you want to be notified on your phone, this can get very expensive and complicated. Why spending money on a GSM modem and a prepaid phone card when you can get the same benefits for free using AWS SNS? Luckily, there is another way.
Use the comment section and tell me your thoughts about this.
If you never had any contact with AWS (Amazon Web Services), you can create an account for free at aws.amazon.com.
But, what is AWS SNS? AWS Simple Notification Service (SNS) makes easier to send notifications to your phone or email address. It allows you to send 100 SMS and 100.000 emails to be sent each month for free (at the moment of writing this). I proved that it’s easy to work with AWS on how to publish temperature and humidity to CloudWatch. You can compare this service with the Observer design pattern.
The first thing that we need it's a way to give permissions to our Rasp to publish SNS topics. In the post mentioned above, I showed how to give permission to the CloudWatch service. The process is very similar, but we need to give access to AWS SNS instead. Please give the following permission policy to your IAM user, AmazonSNSFullAccess. Don't forget to save the AWS access key id and secret access key in a safe place.
After we have the access keys we need to go to AWS SNS Console and follow this tutorial created by AWS to create a topic. After you successfully created the topic, save the topic ARN, we will need it later.
I said that we will send the notifications to our phones and emails, we need to add them as subscribers to the topic that we just created. Use the guidance provided by the AWS to register them. For email addresses don't forget that you have to confirm your registrations, strangely, for a phone, you don't have to confirm that you want to receive notifications.
What do I need to get started?
It's very easy to integrate the AWS SNS functionality in your project. In order to prove this, I will use a project that detects if the door is open or closed. I will modify this project to send notifications with the door status (open/close).
To give you a little context about the project, it uses an ultrasonic sensor to read the distance from the nearest object. When the door is opened/closed the distance increase/decrease as well. To determine if the door status it uses an if/else code block using a fixed distance to compare against. At a first glance this doesn't seem a problem, but if the door is opened, the program will output:
Door Open # 1 notification
Door Open # 2 notifications Door Open # 3 notifications
Door Open # n notifications
Every time this will run, it will send a notification. Because the number of notifications from the free tier is limited we need to make some changes in order to send only 1 message. Even if the money wasn't a problem, it would be very annoying and not cost effective to send so many alerts in a short span of time.
How can I send the messages only once?
After searching a little, the solution that I stumbled upon is to observe the percentage change between 2 consecutive distances (also known as Delta).
We put the sensor at 4cm from the door, with the door closed the output is ~4cm. When the door opens, the distance will significantly increase. The reverse applies equally when the door closes, the distance significantly decrease. In this case, significantly means that the distance increase/decrease by more than 100% (you can increase or decrease this value as you like).
Let's suppose for simplicity that we read 4cm and for the next point we read 20cm. You can notice even if from 4cm to 20cm it's not much it will give a huge output (20cm - 4cm)/4cm * 100 = 400%. Because 400 breaches our threshold of 100 we can say that the door is Open or Close.
Note: If the door opens (or closes) very slowly this algorithm won't catch the status change, before implementing this make sure that you don't have any ninja or cats in the house in order to be effective.
Take me to the code
In the below snipped I focused mainly on the AWS part of the code, the part that is focusing on the ultrasonic sensor can be found here.
For Python 2 (if you use Python 3 please search for the equivalent commands), in order to be able to run the code, you will need to install the AWS SDK in Python, who is called boto3.
pip install boto3
If you don't have pip you can install it using the following command
sudo apt-get install python-pip
Let's do the most important things first so that we don't forget, replace INSER_AWS_ACCESS_KEY, INSER_AWS_SECRET_ACCESS, and INSER_TOPIC_ARN with your own.
In order to publish the message to our listeners, we need to use the publish method from the SNS client API. This method has the following parameters that we will use:
- TopicArn - this is the topic identification (ARN)
- Message - the message that will be sent in the email/SMS, be careful with the text size because an SMS allows only 153 characters
- Subject - (optional) this is used only in the emails (an SMS doesn't have a subject)
For a comprehensive documentation about SNS you can check the following page, you can find details to build more sophisticated systems using this service.
import RPi.GPIO as GPIO import time import boto3 AWS_ACCESS_KEY = 'INSERT_AWS_ACCESS_KEY' AWS_SECRET_ACCESS = 'INSERT_AWS_SECRET_ACCESS' TOPIC_ARN = 'INSERT_TOPIC_ARN' # should similar with this arn:aws:sns:us-east-1:1234567890:door-status # .... # missing functions/constants can be found here # https://thehumblecode.com/blog/how-to-detect-your-door-activity-using-raspberry-pi-and-hc-sr04/ # ....
def publish(snsClient, message):
# replace the TOPIC_ARN with your own
response = snsClient.publish( TopicArn=TOPIC_ARN,
Message=message, Subject='Door status' ) print ("Published with id %s " % response) def percentChange(current, previous, difference): increase = current - previous increasePercentage = increase / previous * 100 if increasePercentage > difference: return True return False if __name__ == '__main__': try: snsClient = boto3.client( 'sns', aws_access_key_id=AWS_ACCESS_KEY, aws_secret_access_key=AWS_SECRET_ACCESS, region_name='us-east-1' ) currentDistance=distance() previousDistance=currentDistance while 1: currentDistance = distance() print ("Distance = %.1f cm" % currentDistance) if percentChange(currentDistance, previousDistance, 100): message = "Door opened. Distance greatly increased from %.1f cm to %.1f" % (previousDistance, currentDistance) print (message) publish(snsClient, message) elif percentChange(previousDistance, currentDistance, 100): message = "Door closed. Distance greatly decreased from %.1f cm to %.1f" % (previousDistance, currentDistance) print (message)
publish(snsClient, message) previousDistance = currentDistance time.sleep(1) # close execution by pressing CTRL + C except KeyboardInterrupt: print("Intrerrupted by user") pass finally: print("Program stopped") GPIO.cleanup()
Run the code using the following command on the terminal and press CTRL + C to cancel anytime.
I hope that you find this useful, AWS SNS is a tool that can come in handy in some situations and has a lot of potential for future projects.
If you encounter any trouble or have any curiosity, feel free to use the comment section to share your feelings about this.
But most importantly, don't stop learning!