Things used in this project

Hardware components

Software apps and online services

Google Assistant

IFTTT

Python Flask

Story

Purpose

2019 is approaching, so I wanted to make a New Year's resolution to learn more about the world. I thought the best way to accomplish this was by making a random fact printer. It would go to a webpage, take a random fact, and print a receipt with the fact on it.

Web Scraping

So you might be wondering, how do you get text from a webpage into something that can be printed. Most webpages contain thousands of lines of text to sort through. That's where web-scraping comes in. I decided to use a Python library called BeautifulSoup, which allows you to parse an entire HTML document into a manageable tree of tags. The website I used to get the facts is http://randomfactgenerator.net due to its simplicity, and how it changes each time the page is loaded.

The code I wrote first gets the page's text by using the urllib.request module, then it gets parsed by the BeautifulSoup constructor. Now comes the question of accessing a specific part of the page. The webpage is made of three main divs each with an id of 'z'. So I can find them with

tag = parsedHTML.find_all('div',{'id':'z'})[0]

and since I only need the first fact I can use [0] at the end to get the first element. But there's a problem; there's a lot more than just the fact in the div, so I will use a regular expression (regex) to isolate the fact from the rest of the div with

div= re.search('<div id="z">(.+?)<br/>',str(tag))fact = div.group(1)

Now that the text is isolated, I can simply return it in a function.

Server

The Particle Photon needs a way to access a fact each time it requests one, meaning I have to make a server. Thankfully, there's a nice Python micro-framework called Flask that allows anyone to create a simple, yet effective, local server that other programs can use to fetch data. It begins by importing Flask and creating an app with

from flask import Flask, requestapp = Flask(__name__)

and then defining a route that will be accessed with

@app.route("/fact", methods=['GET'])

Just below this will go the function that gets called when the route is accessed. Inside of the function will be the webscraping code that at the very end returns the fact in plain text. Make sure to put

app.run(host='0.0.0.0')

at the very end of the script to allow for the server to run on the local network and not just on your machine.

Photon Client

Since I want to use a Particle Photon for this project due to its web connectivity, I first had to figure out how to send GET requests to a server. There's a library called HttpClient that allows for very easy requests. All I had to do was set the port, path, and IP, then create a cloud function that would create a request with

http.get(request,response, headers);

The response text can be retrieved with

response.body

letting the fact get printed with

printer.println(response.body);

Printer

If you have ever gone to a store there is a good chance that you have seen a thermal receipt printer. They work by heating up dots in certain patterns to print text and images onto a special paper that turns black when heated. Adafruit has a mini version of this that is controlled via UART. I am using this one and you can follow the guide here.

This image belongs to Adafruit

It's extremely easy to print out text with it, making this printer perfect for my purposes.

IFTTT

IFTTT is a great website for setting up different causes and events between cloud services. Since I wanted to use Google Assistant as my trigger, I created a new applet and set the "this" portion to use the Google Assistant service with the "Print a fact" trigger word.

For the "that" portion I used the Particle service, utilizing the cloud function that gets called each time the right words are said to the Assistant.

Particle Code

C/C++

// This #include statement was automatically added by the Particle IDE.#include<HttpClient.h>// This #include statement was automatically added by the Particle IDE.#include<Adafruit_Thermal.h>HttpClienthttp;http_header_theaders[]={{"Accept","*/*"},{NULL,NULL}};http_request_trequest;http_response_tresponse;Adafruit_Thermalprinter;voidsetup(){Serial1.begin(19200);printer.begin(&Serial1);Serial.begin(9600);Serial.println("ready");Particle.function("fact-print",print_fact);request.hostname="192.168.0.48";//Local IP of the machine running the flask server goes hererequest.port=5000;request.path="/fact";printer.setTimes(35000,2100);}voidloop(){}intprint_fact(Stringdata){Stringfact_returned="hi";http.get(request,response,headers);Serial.println(response.status);Serial.println(response.body);printer.setSize('M');//printer.print('Did you know:');printer.feed(1);printer.println(response.body);printer.feed(3);printer.setDefault();return0;}