Aquaponics: Arduino Email & Text Messaging

With all of the lauded benefits of aquaponics, there are a number of drawbacks and they primarily lie in the need for electricity.  Typically there is at least one pump, but if you also use grow lights, water heaters and other electronics, you'll inevitably increase possible points of failure.  Wouldn't it be nice if you knew right away when pumps fail, grow lights burn out or don't come on, water heaters die, water temp plummets, a grow bed or fish tank springs a leak or overflows, humidity gets too high/low or the summer sun roasts your greenhouse?

Automation can immediately act to correct some of these conditions but sometimes you don't have a backup pump, grow light or stock tank heater.  Leaks, especially in basement systems, can ruin property if it's not addressed quickly.

What you want is a way to know what's going on as it happens and a very good way of doing that is through text message or email.  That's what this guide is all about and it's not unique to aquaponics or hydroponics - it can be used any time the Arduino needs to alert you of a sensor reading.

The Arduino Data Acquisition and Control System (ADACS) projects in Automating Aquaponics with Arduino use the mail API to notify owners of failed/blocked pumps, when environmental conditions move outside of user-defined ranges, and when grow lights fail or don't turn on.  Additionally, you'll be notified when the Arduino has failed to connect to the webapp for a set period of time to indicate a potential power loss or loss of an internet connection.  Knowledge of what is happening in your system is the most powerful tool of all and when you combine the Arduino in your aquaponics or hydroponics system, you get an inexpensive means of acquiring that knowledge.

How It Works
Like all of our web-based projects we'll use Google's cloud infrastructure, App Engine.  We'll set up an Arduino Uno with two push buttons, which, when pressed, will send a web request to App Engine and prompt either an email or a text message.  The client consists of a very basic form to collect the designated email address and text address.

1 x Arduino Uno R3
1 x Arduino Ethernet Shield R3
2 x Momentary button or switch
2 x 10k ohm resistor
1 x Small breadboard
Breadboard jumper wires

Arduino-1.0.3 IDE
Google App Engine Python SDK: 1.7.4
Python 2.7
Ubuntu 12.04*

*These instructions are probably very easy to translate for Windows or Mac, but as we have neither I can't help you there.

Step 1:  Create a New App Engine Application
The first step will be to create a new application on App Engine.  As all of our web application use App Engine, we've created a standalone tutorial to cover it: Creating a New Application.

Step 2:  App Engine - Configure app.yaml
  • The email alerts reside in a file called  We need to add that file to our app.yaml file, Fig 1.
Fig 1.  Add alerts to app.yaml
Step 3:  App Engine -
  • In the typical MVC (Model, View, Controller) pattern, we need to create a model of our data, which resides in and is imported to the files that need to access it.
  • We have one class to create, the UserPrefs class, which has three properties
    1. Time zone offset - not used in this tutorial
    2. Email Address - string property
    3. Text Address - string property
Fig 2.
 Step 4:  App Engine - and Templates
  • Open and add the import statements, Fig 3.
Fig 3. import statements
  • The first three imports are used to display the templates and run the application.  The users import is used to get the email address of you (the email address you used to create the application).
  • models is used is the file containing the UserPrefs data, which we covered in step 3.
  • consists of just two classes: MainPage and SaveAddress. You can see MainPage in Fig 4.  
Fig 4.  MainPage class.
  • The title of the page is sent to the header template, which you can see in Fig 5.  This is how data can be passed into generic templates, reducing redundant programming.
Fig 5.  The first part of header.html
  •  In order to send emails or text messages you'll need to provide an address, so we add a very simple form to header.html.  You can see the complete file in Fig 6.  The form consists of two text fields and two buttons.  Each button is given a JavaScript onclick handler discussed in the next step.
Fig 6.  Full header.html file
  •  footer.html is a truly uninspiring file and only consists of closing tags
Step 5:  Email & Text Messages
A word on email addresses.  The email address you put as the sender must be an email address associated with the account you used to make the webapp.  You can also invite other Gmail addresses to be admins.  The email address you are sending to can be any valid email address.
Text messages can be sent through an email client such as Gmail given you format the address correctly.  Here is a link on the different formats carriers use for SMS and MMS.  We have only confirmed the Sprint format so I will use that as the example.

Sprint's SMS email format looks like this:
<your phone number>
A Sprint user would substitute their phone number in and use this for the text message box.

Step 6: JavaScript and Form Processing
  • With our template and form in place, we will use JavaScript to send an asynchronous request to the server to process the form.  I've separated the JavaScript into two separate files.  The first is utils.js, Fig 7, and contains the function to create a request.  Looking back at Fig 6, you'll see utils.js is loaded before our second JavaScript file, main.js
Fig 7 - utils.js
  • Next, main.js contains the two onclickhandlers we referenced in the form.  I created them separately for readability in this tutorial, we could have easily created a single button to do this work. When a save button is clicked, a series of events takes place and you can read that in the comments.
Fig 8.  main.js
  • The webapp code to process the JavaScript requests is the second class in, SaveAddress.
Fig 9.  SaveAddress in
  • The JavaScript request is parsed and the UserPrefs entity with the email address you used to create the app used as the key_name.  If the entity exists, you will update the emailAddress or textAddress properties, otherwise a new entity is created.  Finally, the entity is put into the datastore and a response is made.
Step 7:  App Engine -
  • has one class, Alert, used to handle the Arduino request.  There is also one function, SendAlert used to send an email or text message.  First we list our imports
Fig 10. import statements
  • The Alert request handler parses the request from the Arduino to determine the type of alert you want, email or text, Fig 11.
Fig 11.  Alert request handler
  • The request handler for the Arduino parses the request to find out which type of alert you want, text or email.  Then it calls the SendAlert function passing in the type of alert and a message.  This makes the alert function generic and reusable.
Fig 12.  SendAlert
Step 8: Arduino - Fritzing Diagram
  • The circuit for this tutorial is very straight forward and consists of two push buttons.  One push button is used to request an email, the other a text alert.
Fig 13.  Fritzing Diagram
  • In Fig 13 you see a tiny breadboad sitting on an Arduino Uno R3.  In reality, the breadboard resides on an Ethernet Shield, or better yet, a proto shield on an ethernet shield on an Arduino R3.
Step 9: Arduino - Code
  • Start by setting up the Arduino with your assignments
Fig 14.  Arduino assignments and imports
  • The setup loop begins the serial output and the Ethernet.  It sets the pin mode for the pushbuttons to INPUT and finally notifies the user that setup is complete.
Fig 15.  Arduino setup loop.
  • The operating loop monitors digital pins two and three to see if the push buttons have been pressed.  If they have, we call the sendAlert function with the type of alert we want.
Fig 16.  Operating loop
  • sendAlert outputs via serial the type of alert being requested.  Then it creates a GET request to the Arduino and finally outputs the response to the screen.
Fig 17.  sendAlert Arduino function
  • The final two functions in the Arduino program are our normal response parsing and httpRequest functions.
Fig 18.  HTTP response parsing and request functions
And there you have it - two buttons to send either a text message or an email.  While the button format may seem useless think about this - the Arduino read the state of a pin before making the request and the GET request was generalized to allow either button to request the same function.

By extension, the Arduino can read the state of any input pin, analyze the reading via conditionals and send an alert if it needs to.  The Arduino Aquaponics code in the ADACS is rather large, so rather than apply conditionals on the Arduino, the values were automatically sent to App Engine and App Engine applied the conditionals to decide if an alert was needed.  This freed up valuable programming space and extended the number of conditionals that could be applied.


  1. Is it possible to send commands via sms?

    1. Not that we have found.

      If you want to send commands at will to the Arduino from AppEngine, you can implement REST, which requires port forwarding on your wireless router.

    2. This comment has been removed by the author.

    3. I don't think I understand what you are trying to do. Can you explain a little bit more?

    4. This comment has been removed by the author.

    5. I see now, I missed the GSM/GPRS Shield part. Unfortunately, none of us here have experience with these shields. From a quick glance at the official Arduino GSM Shield:

      "You can only place and receive SMS with other SIMs on the Bluevia network. It's not possible to create a server that accepts incoming requests from the public internet. However, the Bluevia SIM will accept incoming requests from other SIM cards on the Bluevia network."

  2. Hello,
    Excellent tutorial. I was since a certain time looking for an elegant way to send emails when my Arduino's measured value exceeds a certain threshold.
    Unfortunately I am stuck (GAE and Python are new to me) in the email address and text address save process, nothing happens when I hit the "save" button. It should display the "Saved" message .... :-(
    Can you help me?
    I was wondering if you could eventually make the source code available for download.

    When I press the save button, in the app engine log I only get:
    2013-05-02 18:02:10.079 /saveAddress? 404 52ms 0kb Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31 - - [02/May/2013:09:02:10 -0700] "GET /saveAddress? HTTP/1.1" 404 188 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31" "" ms=53 cpu_ms=0 cpm_usd=0.000021 app_engine_release=1.7.7

    Kind regards,

    1. Hi Pascal,

      It looks like the server is sending you a 404 message - the link isn't found. From what you put in the log above, it looks like you might have a spelling error:


      The default code does not display the return message when you save your email address. If you look at Step 6, bullet point two, you'll see the five lines of JavaScript for saving an email or text address.

      If you want to see the 'Saved' message, add this line between steps four and five (making it number five).

      // 5. Display return message
      request.onreadystatechange = function() {
      if (request.readyState == 4 && request.status == 200) {

      Let me know if this works for you.

  3. Hi!

    Thanks a lot for your prompt answer!

    I did a small mistake while modifying my e-mail address and application name in the log extract.
    The 2 "a" in the application name was actually a typo.

    Nevertheless I took a few more time in researching errors, and there were more than a few:
    1. A few typos from myself when typing the code

    2. in app.yaml
    Was missing the url to the alert app
    - url: /alerts.*

    3. in
    a) Missed the webapp.WSGIApplication statement at the end of the Alert class:
    app = webapp.WSGIApplication([('/alerts', Alert)], debug=True)
    b) The SendAlert function had to be placed before the Alert class, otherwise the class would not find the function (elementary!)

    4. in
    Was missing the SaveAddress Class/url information in:
    app = webapp.WSGIApplication([('/', MainHandler), ('/SaveAddress', SaveAddress)], debug=True)

    5. in main.js
    Error from the tutorial in the saveEmailAddr javascript function on the url var definition
    var url = '/saveAddress?Address=' + escape(address) + '&Type=email'
    Correct should be (just one character should have been in upper case);
    var url = '/SaveAddress?Address=' + escape(address) + '&Type=email'

    I spent quite a few time in debugging, but the Google App Engine Log function was very helpful.
    My Arduino, connected to a PING))) ultrasonic sensor is now able to send me an email but also a text message whenever the level of water (I plan to install it on a water tank) reaches a critical value!

    I would to thank you again for the "Aquaponics Arduino Email and Text Messaging" tutorial.
    This help me a lot! Keep the good work going!

    Kind regards from France,