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 use the receipt printer as an IOT printer for Alexa (or Google Home, or Siri, etc)
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.
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.
To connect to the Pi remotely, 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.
This brings us to the Pi's terminal interface, where the first thing we want to do is make sure the software is up to date, so run:
sudo apt-get update
With the software updated, we can now 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
Then we can jot up a nice little "Hello World" test script.
#!/usr/bin/python from escpos.printer import Usb p = Usb(0x0416, 0x5011) p.text("Mini IOT Printer\n") p.close()
What good would a printer be without something to print? I wanted to enable functionality to print from different internet services. 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.
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:
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 to print 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:
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.
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-linux-arm.zip unzip ngrok-stable-linux-arm ./ngrok authtoken [insert your auth token here] ./ngrok http 5000
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.
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
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
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!
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. Now go and see what you can come up with!