Introduction: Alexa Printer | Upcycled Receipt Printer

I am a fan of recycling old tech and making it useful again. A while ago, I had acquired an old, cheap thermal receipt printer, and I wanted a useful way to re-purpose it. Then, over the holidays, I was gifted an Amazon Echo Dot, and one of the features I used most was adding groceries to my shopping list. So I thought it'd be cool to combine the two and use the receipt printer as an IOT printer for Alexa (or Google Home, or Siri, etc). Let's see what it'll take to do make this idea a reality.

Supplies

Here's the parts I use for this project:

  1. Cheap generic thermal receipt printer (needs to support ESC-POS)
  2. Amazon Alexa Device (other "home assistant" devices will probably work as well)
  3. Raspberry Pi Zero Wireless
  4. 7805 5v Regulator
  5. 10μf Capacitor
  6. 1μf Capacitor

Other things I use for this project are:

  1. If This Then That (IFTTT.com)
  2. Soldering Equipment

Step 1: Setting Up the Raspberry Pi Zero W

The first step is to get the old receipt printer printing again. I chose to use the Raspberry Pi Zero W as the controller because of it's cheap price and small size. It's actually small enough to fit inside the receipt printer case itself, so there's no external connections! The Pi Zero W also has built in Wifi so everything is basically integrated into it's small size.

To get the Pi up and running, we need to download the Raspbian OS and burn it to a microSD card using a program such as Etcher. Insert it into the Pi along with an HDMI cable, keyboard, mouse, and then power.

When the Pi boots up and you're at the desktop interface, you can connect to your wireless by clicking on the wireless icon in the upper right and selecting the name of your wireless connection. Then if you right click on that same wireless icon, you can go to the network settings and set a static IP address so that we can easily connect to it over the network. Finally, you want to click on the main menu and select the "Raspbian Configuration Editor" and under the "Interfaces" tab, make sure SSH is enabled. Then save it and reboot your Pi.

Step 2: Printing From the Pi

Once the Raspbery Pi has been rebooted, it should be connected to your wireless network with a static IP and with SSH enabled. So now we should be able to connect to it remotely from any other computer. To do that, you'll need an SSH client. For Windows, a good client is Putty. You can connect to it using the Pi's static IP address that we set earlier. Then you can login using "pi" as the username and "raspberry" as the password.

After a successful login, we should now be at the Pi's terminal interface. Here we can type in commands that will execute on the Raspberry Pi. For instance, one of the first things we want to do is make sure the software on the Pi is up to date. So, in the terminal we can type:

sudo apt-get update

This command will update the software repositories on the Pi. Next, we can install the ESC-POS printer software and required libraries.

sudo apt-get install python3 python3-setuptools python3-pip libjpeg8-dev
sudo pip3 install --upgrade pip sudo pip3 install python-escpos

With that done, we can now connect the Printer to the Pi's Micro-USB port (using an adapter) and turn it on. Then in our terminal we can create a little python script

nano hello_world.py

And in it we can add this python code

#!/usr/bin/python
from escpos.printer import Usb p = Usb(0x0416, 0x5011) p.text("Mini IOT Printer\n") p.close()

Exit it (CTRL-X), save it (CTRL-Y) and run it to test it out

python3 hello_world.py

Step 3: Connecting to the Internet of Things (Part 1)

What good would a printer be without something to print? I wanted to enable functionality to print from different internet services, such as Alexa. So how can I accomplish that? One option is to choose a specific internet service, track down their API documentation and write an application based on their API. But I choose to go the lazy route...

There's a great website called "If This Then That" which triggers actions for different internet services (Alexa, Google Home, Gmail, Facebook, Instagram, Twitter, etc) based on a set of criteria. For instance, "if" I post to Facebook (this), "Then" send me an e-mail (that).

So for the first half of this, I signed up for a free account, you can start creating a new "applet" for the different services you want to trigger. The "This" part of my applet will be Alexa. There are a lot of Alexa triggers to choose from, but I'm going to select the one that says "Ask what's on your shopping list". And we ultimately want it to trigger a Python script on the Raspberry Pi, so for the "That" portion of the script, we want to choose Webhooks.


In the Webhooks option, we can add a URL that points to our Pi, which we'll come back to later. We can leave the Method field as "Get", and for the content type select "Plain Text". For the Body field, click "Add Ingredient" and select "Entire List". This will send the entire shopping list as a Get request.

Step 4: Connecting to the Internet of Things (Part 2)

The previous step takes care of the "Internet" part, so now lets work on the "things" part using the Raspberry Pi. In order to communicate with the "If This Then That" webhooks applet, we need to set up a web server on the Raspberry Pi. There are many different ways to set up a web server, but considering I ultimately want to run a Python script, I decided to use Python's Flask server.

The Pi has all the Flask libraries pre-installed, so all we need to do is start writing a test script:

nano flask_test.py

And in it, let's add some code that serves a simple web page.

#!flask/bin/python
#IMPORT THE FLASK LIBRARIES from flask import Flask, request #CREATE A FLASK VARIABLE app = Flask(__name__) #CREATE AN 'INDEX' PAGE @app.route('/') def index(): return 'Your Flask server is working!' #RUN THE PROGRAM if __name__ == '__main__': app.run(debug=True, host='0.0.0.0' )

Now just save the program and run it using this command:

sudo python3 flask_test.py

You'll see by the command response that the default port that Flask runs on is port 5000. So in a web browser, if you type in your Pi's IP Address:5000, you should see the text "Your Flask server is working!"

We have our test Python code from earlier that prints to our receipt printer, and we have our test Flask server. So next we need to combine them and incorporate some code that pulls the data from our Webhook applet. Let's create a new Python file:

nano iot_print_server.py

And within it, add the following code:

#!flask/bin/python
#IMPORT THE FLASK AND PRINTER LIBRARIES from flask import Flask, request from escpos.printer import Usb #ASSIGN VARIABLES FOR THE PRINTER AND FLASK p = Usb(0x0416, 0x5011) app = Flask(__name__) #CREATE 'INDEX' PAGE @app.route('/') def index(): return 'Your Flask server is working!' #CREATE "PAGE" CALLED "LIST" FOR PRINTING ALEXA SHOPPING LIST @app.route('/list') def list(): #CAPTURE "GET" DATA FROM IFTTT WEBOOKS content = request.get_data() #CONVERT RAW DATA TO STRING str_content = str(content) #DIVIDE DATA INTO SEPERATE LINES str_split = str_content.splitlines() #SEPERATE WORDS BY COMMA AND ADD TO A NEW LIST newlist = [] for word in str_split: word = word.split(',') newlist.extend(word) #REMOVE FORMATTING MARKS rmv_marks = [s.strip("b'") for s in newlist] #PRINT HEADER #print("Shopping List\n") p.text("Shopping List:\n") #ENUMERATE AND PRINT EACH ITEM IN LIST r = 1 for x in rmv_marks: #print(str(r) + ". " + x + "\n") p.text(str(r) + ". " + x + "\n") r += 1 #RETURN RESULTS return 'x' #RUN THE PROGRAM if __name__ == '__main__': app.run(debug=True, host='0.0.0.0')

You can run it to see if it returns any errors, but it won't work with our webhook yet because as of right now, the server is only running locally. There's no external URL for the webhook to connect to yet. We could set up port forwarding on our router and just use our external facing IP address, but that's not really too secure. As an alternative, I decide to go with NGROK.

Step 5: Setting Up External Access With Ngrok

Ngrok sets up a secure connection to your network without having to expose your external IP or mess with port forwarding. After signing up for a free account, it gives you an authorization token. Then on your Raspberry Pi, you can download it, unzip it, connect your auth token, and then run it on port 5000:

mkdir ngrok
cd ngrok wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable... unzip ngrok-stable-linux-arm ./ngrok authtoken [insert your auth token here] ./ngrok http 5000

***IMPORTANT***
The free version of Ngrok doesn't give you a static address, so everytime you re-run Ngrok, it'll give you a different address. If you want a static address so that you don't have to keep re-editing your Webhook, then you'll need to pay for an upgraded account.

A free alternative to Ngrok that offers static IP's is called "Serveo" at www.serveo.net

************************

On the resulting screen, it gives you a forwarding address (http://random-string.ngrok.io) that you we can use in our Webhook applet. So going back to "If This Then That", in the URL field, enter your Ngrok forwarding address and point it to the "list" page on our Flask server. It should look something like this

http://random_string.ngrok.io/list

Then go ahead and save the changes.

To test it out, keep Ngrok running, open up a new terminal, and run our python script. With both items running, ask Alexa what's on your shopping list. After a minute or two, it should print out the results. If you want it to print immediately, just go to your Applet on IFTTT and click "Check Now". If everything goes well, the receipt printer should print out what's on your shopping list!
The final bit of code we need to add is a way to autostart ngrok and our flask server every time the Pi starts up. We can easily do that by making our Python script executable:

chmod +x iot_print_server.py

Then we can edit our /etc/rc.local file so that it looks like this:

#
# By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi #autostart ngrok and point it to your auth file ./home/pi/ngrok/ngrok http -config=/home/pi/.ngrok2/ngrok.yml 5000 #autostart the printer python script sudo python3 /home/pi/iot_receipt_printer.py & exit 0

Step 6: Adding the Pi to the Printer

The receipt printer I have has a lot of empty space inside the casing. And with the Raspberry Pi Zero being as small as it is, I thought it'd be cool just to hide it in the receipt printer so that it looks like one device. The only problem is that the Receipt printer runs on 12v and the Pi runs on 5v. So if we only want one power cable to power both of them, we're going to have to step down that 12v power supply to 5v.

Using a 7805 voltage regulator, a 1uf capacitor, and a 10uf capacitor, I was able to create simple 5v regulator that I connected to the logic board of the receipt printer. I soldered the "-" wire to the common ground, and then I soldered the "+" wire to the "on" side of the power switch so that the Pi would turn on and off when the printer was turned on and off. Using a multi-meter, I tested to confirm that the output was safe for the Pi. Then I soldered on a micro-usb cable and connected it to the Pi. After plugging the cable into the printer and flipping the switch, both the printer and the Pi turned on!

Finally, I drilled a hole to connect the USB cable from the Pi to the printer. I found a place to put the 5v regulator and Pi inside the printer case, and then I put everything back together. So now the printer has it's own self contained web server as well!

Step 7: Taking It Further

If you were able to take a look at "If This Then That", you probably noticed that it has tons of different web services to connect to. So if you don't have an Alexa, or don't care to use one, you can use this project to print from just about anything, such as Facebook, Twitter, Gmail, Google Home, Evernote, Tumblr, Flickr, Wordpress, etc. You can find my code for printing out Tweets on my Github page. Now go and see what you can come up with!

IoT Challenge

First Prize in the
IoT Challenge