Secret Code

Push It, Push It Real Good!

Oliver Higgins

Issue 14, August 2018

This article includes additional downloadable resources.
Please log in to access.

Log in

Sending notifications to a phone or device has always been a daunting task. Using Pushbullet, it becomes incredibly easy!

Push Vs. Pull Notifications

Push

Push notifications are a type of technology for sending data to devices such as phones or tablets. An example would be an SMS message or notification of a "like" on a social media platform. See also WAP, push email, etc. The major point is that the server initiates the notification.

Pull

Pull notifications refer to a notification in response to a poll or some type of server request from an app or device. Say you have an app which asks your Arduino web server "what's the temperature" then displays the result, that's a pull notification. Web browsers used to only utilise "pull" type actions, since all actions were instigated by the browser. However this is changing, with push notifications in regular web browsers now becoming commonplace.

With all the internet-enabled projects, one of the most common questions that we get asked is how can I alert somebody that something has happened? Did the print on the 3D printer finish? Did the water level in your tank just get to a certain point? Did your home-automation system detect a problem that needs attention? Pushing this information to the user in a quick timeframe is often plagued with difficult solutions, or a need to write completely different apps for both iOS and the Android platform.

In previous issues, we’ve sent emails and the like to alert the user, but having a dedicated push will ensure that your end-user (or yourself) is more actively engaged in the piece of information you want them to receive.

Pushbullet began as a simple Chrome browser app, where users could easily push files from their desktop or laptop to their Android phone. Since the launch of the app in January 2013, Pushbullet has evolved into a fully supported application with many new features and the ability to push a variety of items (notifications, files, links, pictures, addresses, and more) between many devices.

flow chart

THE BROAD OVERVIEW

Let’s look at this using a very basic example. We have a situation where we want to monitor the front door of a house. Most importantly, we want to know when the door is opened or closed. We need to know as soon as possible, that this event had happened. It may form part of a more significant system or simple solution.

At a block level, we would have some form of trigger or system that we are testing or evaluating for a change. A simple case could be a magnetic reed switch or a hardware micro switch. We then need some form of microprocessor; the only real requirement here is that it has to have network connectivity. Depending on the outcome of your project, you may find that different systems will be able to do slightly different things.

Assuming we have a working network connection, our job becomes straightforward. We decide that the system will start out with the door shut. The system will boot and then wait until a state in the switch connected to the door changes (this could be done with a loop or an interrupt). Once we have a change noted, the system will send a notification using Pushbullet to as many devices that you have in the group. Once the door is closed the state changes again. You may or may not want to know when this has happened. Using this same principle, we could have a simple sensor to the mailbox, and once the postman has delivered something you will get a notification. Think about all those steps saved!

Using this idea, we can take it one step further and send a picture. Imagine we have a doorbell and a camera; whenever the doorbell is pressed, the system snaps a photo of the person at the door. This photo is then uploaded to the Pushbullet image server, before the system sends you an alert to your phone to tell you that somebody is at the front door, along with a photo of who is standing there.

HOW IT WORKS

Pushbullet offers many different things, but we will be focusing on pushing. At the simplest, we can do three basic pushes, note, link and file. The process itself of creating a push is quite straightforward. Once we know what type of push we are creating, we put together this information and send this to the Pushbullet API server. This is done by building the data and sending it via an HTTP request. The API accepts requests over HTTPS at; https://api.pushbullet.com.

All POST requests must use a JSON body with the content-type header set to application/JSON. Most programming languages have some way to encode objects to JSON, and using the built-in library is recommended, since it will correctly handle newline characters and quotes.

THE CODE AND SETUP

To put this into action, we need to understand a few essential elements. We will be looking at the implementation for both Arduino and Raspberry Pi using Python.

Before the start, we need to head over to pushbullet.com and set up an account. Take the time to link your phone and download the app. If you are a chrome user, then there is also a chrome extension that will let you send alerts to your computer.

NOTE: The note is the straightforward “push”. At its simplest, it contains a title and a body. These should both be considered strings and can contain anything we want.

LINK: A link is fundamentally the same as a note, but it contains one more field: the URL. We embed this in our connection data, but when received on your phone it will take you to the link straight away.

SEND FILE: It is possible to send files and attachments using Pushbullet; however, it is a two-step process. First, we need to upload the file to a web server. In this case, Pushbullet does allow us to use their server, making the process easier. Part two entails sending the push notification with the file attached.

Receiving is beyond the scope of this article; however, there are sections of the library that allow communication to be pushed in both directions.

Arduino/C++

In the case of Arduino, we will be using the ESP8266 libraries and platform. The below code was tested using the NodeMCU (ESP12) and the ESP01. The code below is truncated in sections for clarity. Please see full code in the digital resources. Please ensure that you have the ESP8266 libraries installed in your development environment, and understand how to program your specific device.

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
const char* ssid = "YOURSSID";
const char* password ="YOURPASSWORD";

Our code starts out as per most ESP8266 projects, by importing the ESP8266 WiFi library and also the client library. We then define the required variables for the SSID and password for your local wireless connection.

const char* host = "api.pushbullet.com";
const int httpsPort = 443;
const char* PushBulletAPIKEY = "YOURAPIKEY"; 

With this in place, we define the address for the Pushbullet application programming interface (API). You could hard-code this elsewhere in the code, but if for some reason Pushbullet changes its URL we only have to change it the once. Next is the required port. Last for this section is the API key or access token. Using an access token grants full access to your account, so don’t share it lightly. You need the access token in order to use the API. To find it, log into your account, then navigate to “settings”, and then “account”. Scroll down until you find “access tokens” and then use the “create access token” button.

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.print("connecting to ");
  Serial.println(ssid);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }

The above section of code relates to the establishment and securing of the WiFi connection. The first four lines are simple serial output, showing the user some information. The next two establish the basic elements for the wireless connection, then the system loops until a connection is made. Once connected, the details are output to the following display, the secure client is established, and the connection is checked. Once established we are ready to go and push some messages to our clients.

String url = "/v2/pushes";
  String messagebody = "{"type": "note", "title": "DIYODE Push", "body": "Hello DIYODE!"}rn";
Serial.print("requesting URL: ");
Serial.println(url);

This is a key section. The first line prepares the URL for what version of Pushbullet we will be using. The next line is probably the biggest key element to this whole exercise. This is our payload, and this is where the information is set out for use in our push. We need to format it in a way that it will be delivered as JSON data. In this case, we are sending the simplest form of push in a “note”. The JSON payload looks like the below section of code. It is only shown to give a visual output; changing any of the above parts of the string, will result in a change of the push. You can easily insert variables into this string if you wanted to push information, such as the weather from the location of your project.

With our precious cargo all packed up and ready to go, we now need to send it. The below sections of code prepares the HTTP header. All of the data we need, such as specify that there is JSON data plus the length of our message string, is used and posted using the client.print method. With the header sent, the next line sends the message body or our prepared code for the push.

{"type": "note", "title": "DIYODE Push", "body": "Hello DIYODE!"}
client.print(String("POST ") + url + " HTTP/1.1rn" +
   "Host: " + host + "rn" +
   "Authorization: Bearer " + PushBulletAPIKEY + "rn" +
   "Content-Type: application/jsonrn" +
   "Content-Length: " +
  String(messagebody.length()) + "rnrn");
client.print(messagebody);

Our last piece of code outputs to the user, that the push has been sent. Once complete it waits for the return data from Pushbullet. This is a block of JSON data that contains information such as the success of the push, who it was sent to and what the message was that we delivered.

Serial.println("request sent");
while (client.available() == 0);
while (client.available()) {
  String line = client.readStringUntil(‘n’);
  Serial.println(line);

There is no main loop in this case, as it would just sit there and continually send pushes to yourself.

The key in all this is the messagebody line. In the following section of code you can see the same link, but instead of a note, we have created a link. We change the “note” to link, and then add a section of the code further down the string with “URL” and the address of the link we want to send.

String messagebody = "{"type": "link", "title": "DIYODE Push", "body": "Best site eva!", "url": "https://diyodemag.com/"}rn";

Raspberry Pi / Python

In the case of Raspberry Pi and Python, we are very lucky because all the heavy lifting has already been done for us. With Python installed on your machine, it should also include pip. Use the following code to install the Pushbullet Python library:

pip3 install pushbullet.py

With this installed, we need to include the Pushbullet module then specify the API key. Using an access token will grant full access to your account, so as we mentioned previously don’t share it liberally. You need the access token in order to use the API. To find it, log into your account then navigate to “settings” then “account”. Scroll down until you find “access tokens” and then use the “create access token” button.

from pushbullet import Pushbullet
pb = Pushbullet("YOURAPIKEY")

Next we’ll send a push done with just one line of code. Here we specify the type of push we want to send, push_note, the title of the note and what we want the text to say.

push = pb.push_note("DIYODE Push", "Hello Diyode!")

Next is the link push. This is very similar to the note, but we use push_link and specify the link we want to send in the second parameter.

push = pb.push_link("DIYODE Push", "https://diyodemag.com/")

Unlike the previous Arduino/ESP8266 examples we have not included how to send a file. It is much simpler using a Raspberry Pi, as we have a full operating system and place and storing files is more natural. Using Pushbullet with files is a two-step process.

First we need to upload the file to the Pushbullet server, then we send the push. In the case below the first line specifies the file we will be sending. In this case, it is an image file called “cool_picture.jpg”.

The second line is used in the uploads sequence. With the upload complete we create a new push; this time we use push_file and the file_data is passed across from our upload.

For our example, we are going to push our uploaded file using the push_file method.

with open("cool_picture.jpg", "rb") as pic:
    file_data = pb.upload_file(pic, "picture.jpg")
push = pb.push_file(**file_data)

Finally, if you want to, you can get a list of all the devices that you have connected. This is useful if you want to find out the name of a specific device before sending a single push to it.

print(pb.devices)

Pushbullet has to be one of the most straightforward and elegant solutions that we have found to send alerts to users.

The API is loaded with things far more significant than what we have space for. The opportunities that we have to create rich real-time applications and devices become so much better for the use of this service.

Do You NEED to Push?

You may be asking yourself - "is it essential to use push notifications"? The answer is, it depends.

Push notifications give you instant alerts which are great, but whether it's necessary or not is really around the type of data you're getting, and its urgency.

Say for instance, if you're monitoring remote weather, then you probably want to know the current temperature, humidity, perhaps the wind speed etc. It's perfectly acceptable in this instance to poll the server, generating a pull notification or a data log event of that data. You probably don't need to do it more than once an hour, or perhaps once a day depending on your reason for logging it.

However let's consider weather warnings. In Summer especially, the weather can turn foul quickly. If you're out on the water doing some fishing, it can turn from a nice day out to a potentially life-threatening situation within a VERY short space of time.

If you set up a pull notification / poll to retrieve these alerts, there could be a huge time gap between the alert being issued, and your poll retrieving it. If your polling time is set to 4hrs and an extreme weather alert is posted 5 minutes after your last poll, by the time you check it again (in 3hrs 55mins), the weather could be closing in just as you get the alert - that's not really functional.

In this instance, pull notifications for the weather, but push notifications for weather alerts would make sense - so perhaps a combination of the two is actually the best solution.

Arguably, being alerted to Instagram likes on your latest lunch photo isn't terribly time critical. The app would work fine without push notifications (and indeed if you don't allow push notifications, you still get all the same information when you do manually check the app for any activity updates).

Pull notifications are simpler to implement, while push notifications can be more timely and efficient.

So it's really up to you to determine the best method for your particular application, with consideration for the time-sensitivity of the information being exchanged.