Author: Sam Storino

Hi, I'm Sam. I'm a programmer and a DIYer. When I'm not finding things to build I enjoy cooking, hiking, camping and traveling the world with my best friend. Say Hello!
Get Instagram Posts by Tag Name

Get Instagram Posts by Tag Name

Instagram has a very robust API which will enable you to integrate with it in just about any way imaginable. However, there’s also some public endpoints that may get you all the information you need. One such public endpoint which we’ll be covering here is the ability to grab Instagram posts by tag name without the need to register for the Instagram API.

Goal

It’s good to have goals. Ours are simple:

  • Retrieve Instagram posts by tag name as JSON using the public endpoint. 

Get Instagram Posts by Tag Name as JSON

If you were to navigate to the following URL, you’d be shown public Instagram posts with the tag name selfiehttps://www.instagram.com/explore/tags/selfie/

This is a nice way to browse all posts by tag, starting with the most recent. Now, try adding ?__a=1 to the end of that same URL: https://www.instagram.com/explore/tags/selfie/?__a=1

Pretty interesting, right? By adding ?__a=1, you’re telling Instagram to return the results as JSON, which provides a universal way for us to digest the information with code. 

Why does Instagram allow this? Great question, if you have the answer I implore you to share in the comments.

Making Sense of the JSON Result

Now that we know how to grab a JSON result of the most recent Instagram posts by tag name, we just need to make sense of it. We’ll start by using an online JSON pretty printer to make the JSON blob a bit friendlier to look at. There’s a lot of data, but we’re going to hone in on the nodes property under tag > media. This nodes property contains a breakdown of actual post data.

Below, I’ve highlighted some of the more interesting properties of the post that we’ll be discussing:

{  
   "tag":{  
      "name":"selfie",
      "content_advisory":null,
      "media":{  
         "nodes":[  
            {  
               "comments_disabled":false,
               "id":"1638021685389222559",
               "dimensions":{  },
               "owner":{  
                  "id":"4736824623"
               },
               "thumbnail_src":"https://scontent-iad3-1.cdninstagram.com/t51.2885-15/e35/c0.10.500.500/22860707_489313221440833_4558795553466482688_n.jpg",
               "thumbnail_resources":[  ],
               "is_video":false,
               "code":"Ba7bAtUAuKf",
               "date":1509487423,
               "display_src":"https://scontent-iad3-1.cdninstagram.com/t51.2885-15/e35/22860707_489313221440833_4558795553466482688_n.jpg",
               "caption":"#girl #style #pretty #blogger #beautiful #beauty #fashion #ootd #makeup #instagood #like4like #cool #moda #trend #adidas #shoes #shopping #goals #selfie #inspiration #outfit #look #fit #luxury #nails #model #followme",
               "comments":{  
                  "count":0
               },
               "likes":{  
                  "count":1
               }
            },
            ...

Referencing the highlighted properties:

  • code can be used to get information about the originator of the post. You may have noticed there’s an owner property, too, but for the sake of this article we’ll focus on the code property to get originator information.
  • date is when the post was submitted, and is represented by the number of milliseconds since the epoch.
  • display_src is the URL to the posted image. You can see the image by pasting that URL in your browser.
  • caption is, well, the caption associated with the post. This particular caption is a massive list of tags, one of which happens to be #selfie!

As I mentioned, the code property can be used to obtain information about the originator of the post. This is accomplished by plugging the value into another public API. Replace the <code> tag below with your code property value, and paste the URL in your browser to obtain another block of JSON:

https://www.instagram.com/p/<code>/?__a=1

We are once again provided with a decent chunk of data. Use the online JSON pretty printer we discussed earlier to format it so it’s easier to follow. Here’s a sample of the output, which I’ve shortened a bit:

{  
   "graphql":{  
      "shortcode_media":{  
         "__typename":"GraphImage",
         "id":"1638021685389222559",
         "shortcode":"Ba7bAtUAuKf",
         ...
         ...
         ...
         "owner":{  
            "id":"4736824623",
            "profile_pic_url":"https://scontent-iad3-1.cdninstagram.com/t51.2885-19/s150x150/18161617_288442401613475_2938897407410176000_a.jpg",
            "username":"andysprite",
            "blocked_by_viewer":false,
            "followed_by_viewer":false,
            "full_name":"Andy",
            "has_blocked_viewer":false,
            "is_private":false,
            "is_unpublished":false,
            "is_verified":false,
            "requested_by_viewer":false
         },
         ...

The post owner’s information is under the graphql > shortcode_media > owner property. From there you can get information such as username and full_name, which I’ve highlighted above.

We now have a fairly straightforward way to:

  • Grab the most recent Instagram posts by tag name as JSON.
  • Identify individual post data, and use that data to obtain additional information such as the poster’s name and username.

This is pretty great, we have a lot to work with here. However, the JSON results are paged which means at this point we’ve only looked at the very first set of results. A bit more investigation into the JSON result shows that paging is built in.

Requesting the Next Page of Results

Looking back at the JSON under the tags > media property, you’ll see another property called page_info (it may be easier if you collapse the nodes property, as that can take a lot of vertical space):

{  
   "tag":{  
      "name":"selfie",
      "content_advisory":null,
      "media":{  
         "nodes":[  ],
         "count":321717673,
         "page_info":{  
            "has_next_page":true,
            "end_cursor":"J0HWfjzPwAAAF0HWfjzOAAAAFiYA"
         }
      },
      "top_posts":{  }
   }
}

The page_info property has its own children, has_next_page and end_cursor. You probably guessed this, but if has_next_page is set to false, we’re at the very end of the results. Otherwise, the end_cursor property can be appended to the original URL we used via the max_id query parameter to retrieve the very next set of results. Here’s an example of what that might look like:

https://www.instagram.com/explore/tags/selfie/?__a=1&max_id=J0HWfjzPwAAAF0HWfjzOAAAAFiYA

That’s all there is to paging the result set.

Conclusion

We discussed using a public API to retrieve Instagram posts by tag name as a JSON result. After some investigation, we were able to understand the structure of this result and identify some of the more exciting properties. We’re now equipped with enough information to consume the JSON result in code. 

Bluehost Domain Account Email Forwarding to Gmail

Bluehost Domain Account Email Forwarding to Gmail

Every website deserves its own email with the domain name in the address. I’m using Bluehost for my wordpress blog which comes with several free email accounts, it’s just up to you to make use of them. You have the option to utilize a free mail client, use an existing one, or forward along any received emails to a personal account. I use Gmail as my primary mail client, and want to enjoy the comfort I have in the application while managing my domain account email, so I’ll be setting up email forwarding. Along with forwarding, I’ll want to have the ability to respond from my Gmail account with my Bluehost domain account email as the sender.

Let’s go over the goals of this post:

  • Setup an email with Bluehost
  • Forward emails from Bluehost to your Gmail, and setup Gmail to respond as your Bluehost domain account email

Create Your Bluehost Domain Account Email

A domain account email is one where the domain name of your website comes after the @. For example, [email protected]. Looks pretty good, right? Fortunately, this is incredibly easy to setup.

  1. Log into your Bluehost control panel, then select the Email tab on the left-hand menu
  2. Once selected, enter a solid password (look at that 100/100) and create your account

Bluehost Domain Account Email

Now we have a new email address created which can begin receiving emails. Perfect, now let’s forward those emails to a client we’re more comfortable with like Gmail.

Forward Domain Emails to Gmail

When an email is sent to your Bluehost domain account email, a copy of that email will be forwarded along to the email you specify in the below steps. Email forwarding in this case will allow us to avoid having to manage our email through a separate client:

  1. Back in the Bluehost cPanel, under the Email tab on the left-hand menu, click Forwarders
  2. In the forwarders screen, click the Add Forwarder button. You can also click the Add Domain Forwarder if you’d like to forward any and all emails sent to any Bluehost domain account email you have configured. For now, we’ll stick to just forwarding the onecPanel Forwarders
  3. Fill in the forwarding email account, then click Add Forwarder

    Add Forwarder

That’s it, now your domain email account will have its mail forwarded along to your personal account. Give it a shot: email your domain account email and see if your personal gets a copy. This didn’t work immediately for me, there may be a delay for these changes to propagate. If at first it doesn’t work, give it a little while and try again.

Email forwarding is configured, nice work! Now let’s setup our personal Gmail to allow replying as our domain account email.

Replying to Forwarded Emails as the Domain Account

Gmail allows you to setup additional “send as” accounts when composing a new email. By defining another “send as” email account, we can reply to emails that are forwarded from our website domain account email as the domain account email. Let’s set that up:

  1. Log into your Gmail account
  2. At the top right, click the settings icon Gmail Settings Gear, then choose Settings
  3. In the settings window, select Account and Import, then Add another email addressGmail Add Another Email Address
  4. In the resulting window, enter your domain account email that you’re forwarding from. Leave the Treat as alias checkbox checked, then click Next
  5. You’ll be prompted for the SMTP server, username and password. The SMTP server should be your website domain name prefixed with “mail”. For example, mail.storiknow.com. Your credentials will be whatever you use to log into Bluehost.
  6. Once authenticated, Google will send a verification email to your domain account email. Log into your Bluehost email client and click the verification email
  7. Back in Gmail, compose a new email and verify the newly added account is available in the From field

 

There you have it. We’ve successfully created a domain account email, forwarded emails to our personal account, and configured our personal account to respond as our domain account. This allows seamless receipt and response!

Linux Cronjob Doesn’t Execute Valid Python Script

Linux Cronjob Doesn’t Execute Valid Python Script

I’ve been using cron to execute a Python script used by my Raspberry Pi automatic cat feeder for some time now. After coming up with another script that needs to run on a regular schedule I added a second cronjob entry into the crontab.

That’s easy enough: first, in a terminal open the crontab to reveal existing jobs:

sudo nano crontab -e

Add the cronjob to the crontab by creating a new entry:

* * * * * /home/pi/Documents/Development/CatFeeder.py
* * * * * /home/pi/Documents/Development/Maintenance/Monitoring.py

The CatFeeder.py script has been running without a hitch, while the Monitoring.py script is the one being added.

After saving the file (this is nano, so CTRL+X, Y, Enter to save and exit) I expected the job to run every 60 seconds. However, nothing seemed to be happening. The new script never successfully executed. Meanwhile, the CatFeeder.py script was running flawlessly.

The script is an executable, I made sure of that by running chmod +x Monitoring.py, so that’s not the issue. I double-checked that the script ran without errors by invoking it manually: sudo python Monitoring.py. To no surprise the script ran as expected.

If the script runs fine, and a cronjob I already have in the crontab runs fine, then what gives?

SheBang #!: Specifying the Language Interpreter

There’s a very interesting line of code, or a comment rather, that I’ve noticed floating around in most of the Python scripts I’ve seen:

#!/usr/bin/env python

My tiny brain paid this line little attention at first, “how important could it be”, I thought. Enter the shebang #! character sequence. This sequence is treated as an interpreter directive by program loaders such as cron. That is, it specifies which interpreter to use when executing the script. 

Without this line of code the cronjob will not automatically use Python as the interpreter and will fail to execute the script. Add this line to the beginning of your script and watch your cronjob flourish!

What Was That You Said About the Script Running Without Issue?

It was previously mentioned that the Monitoring.py script executed without issue when invoked manually, like so:

sudo python Monitoring.py

This does indeed run without issue, even without the shebang #! line added to the file. However, the script name is preceded with the interpreter to use, python. If we execute the script a different way we’ll more accurately see what’s happening when the cronjob runs it.

In the terminal use the ./ command to execute the script:

./Monitoring.py

Without the shebang #!, Python is not used as the interpreter, and errors are shown in the terminal:

pi@raspberrypi:~/Documents/Development/Maintenance $ ./Monitoring.py
./Monitoring.py: line 2: import: command not found
./Monitoring.py: line 3: syntax error near unexpected token `1,'
./Monitoring.py: line 3: `sys.path.insert(1, os.path.join(sys.path[0], '..'))'

Now add the shebang #!/usr/bin/env python at the beginning of the script and execute it again. Unless your script has other syntactical problems it should run successfully.

Resolving the Visual Studio “Project Types May Not Be Installed” Error

Resolving the Visual Studio “Project Types May Not Be Installed” Error

I recently received a new work laptop and went through the pains of installing all the necessary software. Of course, things were missed, one of which was the SQL Server Data Tools. We’ve created a number of Report Server Project’s using the SQL Server Data Tools in Visual Studio. When attempting to open one of these projects I received an error stating:

This version of Visual Studio is unable to open the following projects. The project types may not be installed or this version of Visual Studio may not support them

 

Visual Studio Unsupported Project Error
Visual Studio Unsupported Project Error

Visual Studio 2015 certainly supports these reporting projects, so I knew that couldn’t be the issue. I then realized I completely forgot about those poor SQL Server Data Tools (SSDT).

Installing SQL Server Data Tools

SQL Server Data Tools is being used by Visual Studio to create these reporting projects (rptproj, dtproj). In order for Visual Studio to understand how to support them we need to install SSDT:

  1. Open the SQL Server 2016 Installation Center (or whichever version you’re using)
  2. In the installer window, click the Installation tab in the left-hand menu, then choose Install SQL Server Data Tools
    Install SQL Server Data Tools Link
  3. In the feature selection window, select all the SQL Server services, then click nextSQL Server Feature Selection
  4. Lastly, accept the terms and conditions, then click the Install buttonSQL Server Data Tools Install

Now that SQL Server Data Tools is installed with the necessary features, you should no longer receive the “Project Types May Not Be Installed” error when loading your SSDT dependent project in Visual Studio.

 

Active Directory Users and Computers Missing on Windows 10

Active Directory Users and Computers Missing on Windows 10

If you’ve ever needed to maintain any information in Active Directory, you’ve undoubtedly utilized the Active Directory Users and Computers app. According to Microsoft:

Active Directory Users and Computers is a Microsoft Management Console (MMC) snap-in that is a standard feature of Microsoft Windows Server operating systems. It can be used to administer and publish information in the directory.

I recently received a new laptop from work and had to go through the pains of installing all the necessary (and unnecessary) programs. After thinking I finally finished I realized Active Directory Users and Computers was missing. It turns out my WIndows 10 machine didn’t have the Remote Server Administration Tools (RSAT) installed.

Install Remote Server Administration Tools on Windows 10

Microsoft makes installation of the remote server administration tools fairly straightforward. Start by navigating to the Remote Server Administration Tools page, then download the installer and step through the installation wizard. Once the install finishes you may need to reboot your machine. After rebooting, you should see the Remote Server Administration Tools as an enabled windows feature:

Remote Server Administration Tools
Remote Server Administration Tools

Now that Remote Server Administration Tools is enabled you can load up the Active Directory Users and Computers application:

Active Directory Users And Computers
Active Directory Users And Computers
Mounting the Raspberry Pi and Servo Motor to a Dry Food Dispenser

Mounting the Raspberry Pi and Servo Motor to a Dry Food Dispenser

You made it to the end! (or you happened to stumble upon this part of the guide). Looking back, part’s one, two and three weren’t so bad now that you’ve got the hang of things. Here in part four we’re going to mount the Raspberry Pi and servo motor onto the food dispenser.

The goals of this part are:

  • Connect the servo motor to the knob of the dispenser.
  • Cut the threaded rod down to size.
  • Mount the servo to the dispenser.
  • Bind the PVC fitting to the dispenser so the food has a path to follow.
  • Mount the Raspberry Pi to the dispenser.

I chose to connect everything to the dispenser and nothing to the stand. This offers a bit of flexibility: with everything relying on the dispenser the stand can be interchanged. Before we get started, power down the Raspberry Pi: sudo shutdown -h

Connecting the Parts

We’ll start by connecting the servo motor to the knob of the dispenser. I originally did this by using tape which actually worked fine for a while. However, over time the tape began to lose its grip on the knob, preventing it from turning as effectively. The tape has been replaced with zip ties which have been working flawlessly:

  • Take the knob of the food dispenser out of the dispenser.
  • To give the zip ties a flat surface to latch onto, I used a hacksaw to square off the rounded edges of the knob.
  • Wrap and connect a zip tie around the knob and servo, tightening it in place. Repeat this process until the servo is securely fastened. Use the image below as a guide to how I went about doing this.
  • Insert your creation back into the food dispenser.

Servo Attached to Knob

This is great! It looks complete, but what you’ll notice if you tried spinning the motor is that it won’t have anything to grasp onto, so it will spin with the knob. We need to fasten the motor to the dispenser. If you look at the top and bottom of the motor you’ll notice two sets of screw holes. The set that’s furthest away from the center of the dispenser knob is the one we’ll be dealing with. Using the image above as reference, that’s the set of screw holes on the top of the motor.

The screw holes are slightly smaller than the threaded rod, so we’ll need to do a tiny bit of surgery to get the rods to fit:

  • Using your box cutter, carefully cut away a very little piece of the plastic at the smallest point of the screw hole.
  • Try pushing the threaded rod into the screw hole. Did it fit? Then move on down! Otherwise repeat the previous steps until it fits snug.

Now we’ll cut the rod to the appropriate length, drill a couple holes into the dispenser and fish the threaded rods through. With the motor/ knob inserted into the dispenser (like the image above):

  • Measure the distance from the screw hole to the dispenser, then add about an inch or two.
  • Using your hacksaw, cut two pieces of threaded rod to the measured length.
  • Place the two pieces of threaded rod into the screw holes of the motor and push them flush against the wall of the dispenser.
  • Make a tiny mark on the dispenser where the threaded rods touch it. This will identify where we need holes for the rods to fit through.
  • Make an attempt to spin the wheel of the dispenser manually by rotating the knob. If any part of the knob hits the rod you’ll need to trim the knob’s plastic down a bit with your hacksaw.
  • Remove the motor/ knob, and the white rubber wheel from inside the dispenser.
  • Stop: obligatory (but very important) warning to put on your safety goggles, please.
  • Drill two holes slightly larger than the threaded rods into the dispenser where you made your markings.
  • Insert the threaded rods through the holes and fasten them down with a couple of hex nuts.

Did you wind up with this?

Threaded Rod in Dispenser

At this point mounting the motor is pretty straightforward. Before we bring it back into the picture let’s get the PVC fitting attached to the hole of the dispenser. We need two holes opposite one another at the mouth of the dispenser, and two more holes at the top of the PVC fitting.

  • Place the mouth of the PVC fitting flush against the mouth of the dispenser.
  • Use a pen to mark slightly below the lip of the PVC fitting closest to the dispenser. Make another mark directly above that on the dispenser itself. Make the same markings on opposite sides of the PVC fitting and dispenser.
  • Using a drill bit large enough for a zip tie to squeeze through, drill holes where you made the marks.
  • Using zip ties, bind the PVC fitting to the mouth of the dispenser.

The result should look something like this:

PVC Fitting Connected to Dispenser

Now that the threaded rods are in place, add back the motor/ knob. Position the threaded rod through the screw holes of the motor and tighten with a hex nut. You probably won’t have enough space to add two hex nuts. That’s alright, I didn’t either:

Motor Attached to Dispenser

Fantastic, we’re mostly there. We just need to mount the Raspberry Pi to the dispenser and we’re done! I mounted my Raspberry Pi as center to the dispenser as I could, but it doesn’t really matter:

  • Place the Raspberry Pi against the body of the dispenser where you’d like to mount it.
  • Make two markings on the dispenser, one on either side of the Raspberry Pi.
  • Drill two holes into the dispenser where you marked it.
  • Using a zip tie, mount the Raspberry Pi to the dispenser through those two holes.
Pi Mounted to Dispenser
Pi Mounted to Dispenser

Congratulations, you did it! An automated food dispenser is now at your command. 

Conclusion

The Raspberry Pi is an incredible little machine with endless possibilities. I sincerely hope this series of posts was as helpful to you as it was me. It was a long journey, but now you’re prepared to tackle any new DIY Raspberry Pi projects that may come your way.

I encourage you to leave comments letting me know what you think. If anything was unclear I’d appreciate hearing about it.

  • In part one we laid out the plan.
  • Part two we set ourselves up with the power of reading emails.
  • In part three we talked all about controlling servo motors.
  • And here in part four we put it all together to make an impressive new toy.

If you enjoyed this series of posts, please be sure to check out my series on building an automatic cat laser pointer toy!

Controlling a Servo Motor with Gmail and Raspberry Pi

Controlling a Servo Motor with Gmail and Raspberry Pi

You covered part one and part two (good work!), or maybe you didn’t and you found yourself here anyway (welcome). Part three is focused on the servo motor, primarily making it spin. Later in part four we’ll wrap things up by connecting it to the dispenser.

As always, let’s start with what it is we’re trying to accomplish here:

  • Connect the servo motor to the Raspberry Pi’s GPIO header pins
  • Write some code to make that motor functional
  • Tie in the GmailWrapper.py script we wrote in part two so the motor spins when the right email lands in your inbox

Here we go!

Connecting the Servo Motor to the Raspberry Pi

If you’re using the same servo motor as me, it has power, ground and control wires. If you decided to use the standard non-continuous servo motor (which is a viable alternative since we won’t be performing a full revolution), then: power is red, ground is black and white is control.

Connect your male-to-female jumper cables to the servo. Now, using the GPIO diagram below as reference, connect the wires to the Pi’s GPIO headers as follows:

Note: this diagram is for Raspberry Pi’s with 40 pin GPIO, but the below works with 26 pin GPIO as well.

  • power connects to header pin 2 (5v power)
  • ground (black wire for standard servo) connects to header pin 6 (Ground)
  • control (white for standard servo) connects to header pin 12 (GPIO18)

GPIO Pinout Diagram

Here’s what mine looks like (don’t mind the zip tie):

Servo Connecting to Pi
Servo Connecting to Pi’s GPIO

 

Writing Code to Make the Servo Motor Spin

Before getting started, let’s update our Pi to the latest packages and install the GPIO library. Run this in the terminal:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install rpi.gpio

We’re all set. In the terminal, create a new python script using nano: sudo nano CatFeeder.py

Within the CatFeeder.py script, add the following code:

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time

def feed():
    # let the GPIO library know where we've connected our servo to the Pi
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(18, GPIO.OUT)

    try:
        servo = GPIO.PWM(18, 50)
        servo.start(12.5)

        # spin left, right, then left again rather than in a continuous circle
        # to prevent the food from jamming the servo
        for index in range(0, 3):
            dutyCycle = 2.5 if (index % 2 == 0) else 12.5
            servo.ChangeDutyCycle(dutyCycle)
            # adjust the sleep time to have the servo spin longer or shorter in that direction
            time.sleep(0.8) 
    finally:
        # always cleanup after ourselves
        servo.stop()
        GPIO.cleanup()

if __name__ == '__main__':
    # kick off the feeding process (move the servo)
    feed()

Save and exit the nano editor: CTRL+X, then Y, then Enter. Moment of truth, time to make that servo move! Let’s drop back into the Python interpreter, in the terminal:

# remember, hit enter after each line to have the interpreter... interpret
python
import CatFeeder
CatFeeder.feed()

I hope that went smooth for you, because I just got really excited. Welcome to physical computing! You moved a physical object with code, hell yeah.

GmailWrapper, Meet CatFeeder: Putting it all Together

Alright, so we’ve created a way to read emails, and we’ve created a way to move a servo motor. Now we need to combine the two so the servo motor moves when we read emails.

Open CatFeeder.py in nano and add the highlighted lines of code: sudo nano CatFeeder.py

#!/usr/bin/env python

from GmailWrapper import GmailWrapper

import RPi.GPIO as GPIO
import time

HOSTNAME = 'imap.gmail.com'
USERNAME = '<your gmail username>'
PASSWORD = '<your app password or regular gmail password>'

def feedByGmail():
    gmailWrapper = GmailWrapper(HOSTNAME, USERNAME, PASSWORD)
    ids = gmailWrapper.getIdsBySubject('feed cats')
    if(len(ids) > 0):
        try:
            feed()
            gmailWrapper.markAsRead(ids)
        except:
            print("Failed to feed cats, they're starvingggg")

def feed():
    # let the library know where we've connected our servo to the Pi
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(18, GPIO.OUT)

    try:
        servo = GPIO.PWM(18, 50)
        servo.start(12.5)

        # spin left, right, then left again rather than in a continuous circle
        # to prevent the food from jamming the servo
        for index in range(0, 3):
            dutyCycle = 2.5 if (index % 2 == 0) else 12.5
            servo.ChangeDutyCycle(dutyCycle)
            time.sleep(0.8)
    finally:
        # always cleanup after ourselves
        servo.stop()
        GPIO.cleanup()

if __name__ == '__main__':
    # kick off the feeding process (move the servo)
    # we now use our new feedByGmail method to handle the feeding
    feedByGmail()

Save and exit the nano editor: CTRL+X, then Y, then Enter. As always, let’s give it a test. Send yourself an email with the subject feed cats. Drop into the python interpreter once the email arrives:

python
import CatFeeder
CatFeeder.feedByGmail()

Did it work? It did? Excellent! If it didn’t, don’t be discouraged! Python’s support community is huge, you’ll find the answer. Plus, you can always leave a comment below.

Scheduling a Cron Job to Run Our Script Regularly

We have code to move our servo motor when the correct email lands in our inbox, but it currently only runs when we physically tell it to. Let’s fix that by setting up a cron job to run our script every 60 seconds.

In order for the cron job to execute our script, we need to make our script executable. This is done by issuing the following command in the terminal: sudo chmod +x CatFeeder.py

Now we’ll add the cron job. In the terminal: crontab -e. Add the following after the very last commented line (comments start with #):

* * * * * python /path/to/your/script/CatFeeder.py

As Gabe called out in the comments, adding python after the last asterisk (*) in the line above will force the python interpreter to be used while running our script. We’re in the nano editor, so save and exit: CTRL+XYEnter. Easy as Pi (sorry). A job is now running every 60 seconds with the sole task of looking for emails and feeding cats. Don’t believe me? Give it a shot, send yourself an email with the subject feed cats.

A nicety of cron jobs is they’ll continue running automatically if your Pi ever restarts.

Scheduling an Email to be Sent Regularly

We have the code, we have the cron job. Sending an email on demand will cause the servo motor to spin, but what about spinning it on a schedule? That’s where we’ll make use of IFTTT. IFTTT stands for if this then that and allows you to connect two disparate systems based on what they call a “recipe” (trigger and action). For our purpose, we need the clock to trigger an email to be sent (action). Here’s what to do:

  1. Setup an account if you haven’t already
  2. Use IFTTT website or download the app to your phone and log in
  3. In the My Applets section, add a new applet
  4. You’ll see a screen saying if +this then that: click the +this button, then select the Date & Time service.
  5. Select the Every day at trigger, and select the time you’d like the cat feeder to activate, then hit next
  6. Now you’ll see +that, click it and find the Gmail service. You’ll need to connect the service to your Gmail account. Once finished, set the action to Send yourself an email with the subject Feed cats.
  7. Hit next, then Finish

There you have it, every day at the time you specified an email will be sent to your account. If you had any issues setting up the IFTTT recipe, check out this post for a really nice and in-depth walk-through.

Having fun? Here’s Other Ways to Send an Email

Alexa

Alexa integrates nicely with IFTTT. In the IFTTT app, create a new recipe with the trigger (+this) connecting to Alexa. You’ll need to connect the service like you did for Gmail. Once connected, set the action (+that) to send an email, like we did in the previous section.

Hands free feeding at your ready: Alexa, trigger the cat feeder.

The DO Button App

Created by the IFTTT team, the DO Button app and accompanying widget provides a straightforward way to trigger the action. You! You’re the trigger. You setup a recipe, same as before, except you’ll notice there’s no +this. You are the +this. You open the app and click the button, it then triggers an email. This app can also be configured to show on your iPhone or Androids home screen, so triggering the email is even easier.

Conclusion and Next Steps

Part one has goals and items covered, part two has Gmail automation down, and part three provided the spinning of the motor. A lot has been done so far, we’re nearly there. Up for part four? That’s where I’m headed to connect the Pi and motor to the dispenser.

Reading Gmail with Raspberry Pi and IMAPClient

Reading Gmail with Raspberry Pi and IMAPClient

In part one we covered the basics of what we’re trying to build, and what you’ll need to get started. Here in part two we’ll be playing with some python code to interact with our Gmail account using IMAPClient. Later on, part three is focused on the servo motor, while part four connects it all to the food dispenser.

The goal of this part?

  • Setup your Gmail Account with 2-step authentication for a secure way to interact with it through code. 
  • Write some code to interrogate your inbox for an email and mark it as read when found using the IMAPClient library.

Let’s get to it!

Preparing Your Gmail Account with 2-step Authentication

This is not strictly necessary, but a good security practice. If you don’t mind your credentials being in plain text in your code, feel free to skip ahead.

Since we’re going to be using email as the trigger, we’ll need a way to securely log into our Gmail account from code. You could store your credentials in plain text within the code we write, but I strongly discourage that. Instead, make use of Gmail’s two-step authentication and app passwords

I created a new Gmail account for this purpose.

  1. Log into your gmail account
  2. Navigate to the Sign-in and security page
  3. Under the Signing in to Google section, click the 2-Step Verification menu, then follow the instructions to enable 2-Step Verification
  4. Back in the Sign-in and security page right under the 2-Step Verification button you’ll see App passwords
  5. Generate a password
    1. Note: this password will be 16 digits with spaces separating every 4 digits (e.g. xxxx xxxx xxxx xxxx). Please be sure to include the spaces!

The password you generated can be used to log into your Gmail account. We don’t need it right this second, but we’ll be using it to scan for an email that demands we feed the cats!

Writing Code to Read Your Gmail

Now that we have a Gmail account ready to rock, let’s write some code to interrogate it. We’re going to be using the IMAPClient python library for this purpose, and we’ll wrap the calls to this client in our own Python class.

Install IMAPClient now from the terminal: sudo pip install imapclient

Create the GmailWrapper.py Script

Now let’s create our Gmail wrapper class: nano GmailWrapper.py. Within the GmailWrapper.py script, add the following code:

#!/usr/bin/env python

from imapclient import IMAPClient, SEEN

SEEN_FLAG = 'SEEN'
UNSEEN_FLAG = 'UNSEEN'

class GmailWrapper:
    def __init__(self, host, userName, password):
        #   force the user to pass along username and password to log in as 
        self.host = host
        self.userName = userName
        self.password = password
        self.login()

    def login(self):
        print('Logging in as ' + self.userName)
        server = IMAPClient(self.host, use_uid=True, ssl=True)
        server.login(self.userName, self.password)
        self.server = server

    #   The IMAPClient search returns a list of Id's that match the given criteria.
    #   An Id in this case identifies a specific email
    def getIdsBySubject(self, subject, unreadOnly=True, folder='INBOX'):
        #   search within the specified folder, e.g. Inbox
        self.setFolder(folder)  

        #   build the search criteria (e.g. unread emails with the given subject)
        self.searchCriteria = [UNSEEN_FLAG, 'SUBJECT', subject]

        if(unreadOnly == False):
            #   force the search to include "read" emails too
            self.searchCriteria.append(SEEN_FLAG)

        #   conduct the search and return the resulting Ids
        return self.server.search(self.searchCriteria)

    def markAsRead(self, mailIds, folder='INBOX'):
        self.setFolder(folder)
        self.server.set_flags(mailIds, [SEEN])

    def setFolder(self, folder):
        self.server.select_folder(folder)

Save and exit the nano editor: CTRL+Xthen Y, then Enter.

Verifying the GmailWrapper.py Class Works

Let’s do a test: our script is going to log into the Gmail account, search for email with a specific subject, then mark it as read. Before running the code, send yourself an email with the subject feed cats (the search is case-insensitive, by the way).

We’re going to use the Python interpreter to run our tests. In your terminal make sure you’re in the same directory as the GmailWrapper.py class we just created, then:

# press enter after each line for the interpreter to engage

# invoke the interpreter
python

# import our wrapper class for reference
from GmailWrapper import GmailWrapper

# create an instance of the class, which will also log us in
# the <password> should be the 2-step auth App Password, or your regular password
gmailWrapper = GmailWrapper('imap.gmail.com', '<your gmail username>', '<password>')

# search for any unread emails with the subject 'feed cats', and return their Ids
ids = gmailWrapper.getIdsBySubject('feed cats')

# have the interpreter print the ids variable so you know you've got something
ids

# now lets mark the email as read
gmailWrapper.markAsRead(ids)

# exit the interpreter
quit()

If everything went as planned your email should now be marked as read. Pretty neat!

Conclusion and Next Steps

Part one set the goals and outline. Now with part two wrapped up we have the ability to discern whether or not an email exists. With this power we can trigger certain events, such as spinning a servo motor. That’s exactly what we’re going to do in part three, I’ll meet you there.

Later on in part four we’ll be attaching the Pi and servo motor to the dispenser, but before we make anything permanent let’s get that servo spinning.

Automatic Cat Feeder Using the Raspberry Pi

Automatic Cat Feeder Using the Raspberry Pi

After many failed attempts at changing their feeding schedule, our cats are starving by 3:00 AM. What this equates to is many meows until we’re awake. I remembered a post I saw on David Bryan’s blog about his Raspberry Pi controlled automatic cat feeder. Inspired by David, I decided to take a crack at building my own. Here’s what I came up with, and what I’ll be covering in this post.

Goal

An automated way to feed the cats both on demand as well as on a schedule.

This cat feeder will be triggered by email. More specifically, Gmail. That’s right, we’re going to set up a Gmail account that our Raspberry Pi will monitor. When an email arrives with the expected subject, the cat feeder will let loose its goods.

I chose this route to avoid overly complicating the project. Feeding the cats on demand is as easy as sending an email, while feeding them on a schedule is as easy as creating an IFTTT applet. So long as the cats don’t figure out the email account and secret subject, this should be a viable solution.

If you find this series of posts interesting, you might also enjoy the automatic cat laser pointer toy series!

Prerequisites

You should have a configured Raspberry Pi ready to go. I used my original Raspberry Pi Model B (26 GPIO pins), an 8gb SD card and the Raspbian distro (highly recommended). This guide was pretty straightforward and got me up and running in no time.

The Parts

I decided to break this post down into distinct parts for readability:

  • Here in part one we’re introducing what we’re building and the things you’ll need to get it done
  • Part two will cover writing code to interrogate your Gmail account for an email with the subject feed cats
  • Meanwhile, part three is going to focus on connecting your servo motor to the Raspberry Pi and writing code to make it spin
  • And lastly, part four will cover my approach at mounting the Pi and servo motor to the dispenser

The Things You’ll Need for the Automatic Cat Feeder

  • Cereal/ Dry Food Dispenser to hold the cat food. The stand this dispenser came with didn’t have sufficient space to mount the motor on the back end. I wanted the motor to be hidden as much as possible, so this drove me to build my own stand for the dispenser.
  • Servo motor to spin the dispenser. I used this continuous rotation servo motor, though the standard non-continuous servo motor will work just the same, as we won’t be doing a full revolution. 
  • 5V 2A USB Power Adapter to power the Pi and motor. The motor draws a good amount of current, so we need to make sure the power supply is capable of supporting it. I ended up using my iPad charger.
  • 3x Male-to Female jumper cables to connect the motor to the Pi’s GPIO pins.
  • WiFi Dongle, unless you’ll be hard wiring or have a later Raspberry Pi model that comes with the WiFi built in (good on you).
  • I have two cats, so I used a PVC fitting that will split the load into two bowls. Ideally, a 2 inch PVC Double 90 Degree Elbow. They don’t sell them in stores around me, so I settled on the double wye and plugged the center hole.
  • Zip ties, or some other cheap and easy fastener.
  • 1x #8-32 Threaded Rod to fasten the base of the servo motor to the dispenser, keeping it from spinning.
  • 4x #8-32 Hex Nut to tighten the rod in place.

The Tools

  • Power drill if you plan on attaching the Pi and PVC pipe directly to the dispenser.
  • Box cutter if you’re using the threaded rods as a fastener, as they’re slightly too large to fit in the servo motor mounting holes.
  • Hacksaw if you’re going to use the threaded rod from above. It’s a bit too long so we’ll need to shorten it. 

[Optional] Building a Custom Stand for the Dispenser

The stand that came with the dispenser didn’t have enough space behind it for the servo motor to be mounted properly. I wasn’t keen on the idea of the servo being up front, especially knowing my cats with wires, so I went the route of building my own.

I chose to build this using copper piping (had to match our boho theme). It didn’t take long to find something on Pinterest that (mostly) fit our needs. This plant holder was re-purposed to be a dry food dispenser stand. The small square in the middle was sized to fit the base of the dispenser firmly, then copper piping was built around it.

I’m not going to go into the specifics of how this was constructed, but here’s a list of additional parts anyway:

Conclusion and Next Steps

So far we talked about what you’ll need to get started. Head over to part two where we cover writing a python script to read your Gmail account using the IMAPClient library.

Ahead of the game? Part three covers rotating the servo motor, and part four is all about connecting the Pi and motor to the dispenser.