Push notifications to Zato with Tasker

The project this week is to use Tasker to send messages to our Zato ESB when we get notifications on the phone.

So let’s start with the Tasker end of it. I’m using the Notification Listener plugin because it ties in with the standard Android notification access permissions and exposes more than just the title of the notification.

When an incoming notification is received and the plugin is set up to listen, it populates a number of variables in Tasker, including:

  • %nlapp – this will always be the name of the app sending the notification (e.g. “Gmail” or “Whatsapp”)
  • %nltitle – The title of the notification. For messaging apps such as Gmail and SMS this will be the sender’s name.
  • %nltext – the main body of the notification. What this actually contains will depend on the sending app. For Gmail this is just the subject line of the email, but for SMS and WhatsApp it seems to be the entire message.
  • %nlsubtext – This isn’t always populated, but some apps do use it – Gmail, for example, puts the recipient’s address in this one.

What we’re going to do is send a message to our ESB with a few of these fields.

Let’s start off by creating a profile for notification events, selecting the apps we want.

tasker profile setupTo do this, from the profile tab:

  • Tap “+” to create a new profile and select “Event”
  • Select “Plugin” from the “Event Category” list
  • Select “Notification Listener” from the event plugins
  • On the “Event Edit” configuration screen, tap the configuration.
  • Select the apps for which we want to process notifications – for example, Gmail, Messenger and WhatsApp.
  • Tap the tick button to confirm the selection.

We should then see a summary of the variables that Notification Listener populates:tasker notification listener

 

  • Tap the back button to confirm and we should get a “New Task” popup next to the event.
  • Name the task – for example “Send Messsage”.
  • This will take us to the “Task Edit” page where we can tap the “+” to add an action.
  • Select “Net” and then “HTTP Post”

Now we just need to fill in the configuration for the message that we’re going to post:

tasker action edit

The server:port will be the hostname of our server. If we’re posting directly to Zato this will be:

http://<ip_address>:11223

We can also optionally use basic auth by prefixing the address with :@ – i.e:

http://<username>:<password>@<ipaddress>:11223

The path will be the URL that we set up in Zato – for this example I’m using /apis/android

The data / file section is where we build the post message, using the variable names that have been set by the listener:

android notifications with tasker

This will be URL encoded by Tasker when it sends the message, replacing the variables with their values.

It is also possible to change the Content / Type and build a different data format. For example, we could send the data as JSON instead, which would make things a bit simpler at the Zato end.

However, if we stick to the default URL encoding Tasker will manage the encoding of special characters for us. If we were to use JSON we’d run into trouble if one of our variables had, for example, quote characters in it.

It’s better to keep it as simple as possible in Tasker and let Zato handle the incoming format.

And so to Zato.

We’ll create a new service in file android.py:

from zato.server.service import Service
import urlparse
from bunch import bunchify
from anyjson import dumps</pre>

class ProcessNotification(Service):

  def handle(self):

    self.logger.info(self.request.raw_request)

    incoming = urlparse.parse_qs(self.request.raw_request)
    self.logger.info(dumps(incoming))

    data = urlparse.parse_qsl(self.request.raw_request)
    self.logger.info(dumps(data))

    self.logger.info(dumps(dict(data)))

    message = bunchify(dict(data))
    self.logger.info(message.text)

This uses the urlparse library and we’re logging various ways to see the data. Now we need to link this up to a service by creating a new plain HTTP channel in Zato:

And we’re good to go.

If we send ourselves a test email, we can look at the logs and see the various ways in which we can manage the incoming data:

First of all the raw message. Note that if a variable hasn’t been populated within Tasker we’ll just get the variable name. This sort of logging is a handy way to see how different apps populate the Notification Listener variables:

app=Gmail&amp;title=Sean&amp;text=Test+subject&amp;ticker=Sean&amp;subtext=sean%40example.com&amp;summary=%25nlsummary&amp;bigtext=Test+subject&amp;info=%25nlinfotext

Then parsed using parse_qs. Note that the parse methods have done the work of converting our encoded special characters back to text:

{"info": ["%nlinfotext"], "subtext": ["sean@example.com"], "title": ["Sean"], "bigtext": ["Test subject"], "text": ["Test subject"], "app": ["Gmail"], "summary": ["%nlsummary"], "ticker": ["Sean"]}

This method creates an array of values for each key. This is because URL posts can contain the same variable multiple times – you could have multiple titles, for example.

The parse_qsl version returns the key/value pairs as an array:

[["app", "Gmail"], ["title", "Sean"], ["text", "Test subject"], ["ticker", "Sean"], ["subtext", "sean@example.com"], ["summary", "%nlsummary"], ["bigtext", "Test subject"], ["info", "%nlinfotext"]]

We can convert this one to a dictionary object if we know that there’ll only be one instance of each key:

{"info": "%nlinfotext", "subtext": "sean@example.com", "title": "Sean", "bigtext": "Test subject", "text": "Test subject", "app": "Gmail", "summary": "%nlsummary", "ticker": "Sean"}

Finally we can bunchify the result which allows us to refer to individual keys in dotted notation. The last log entry will just be:

Test subject

Obviously we don’t need all of these logged, but this is just to illustrate the options. I prefer the bunchify method because it makes for neater code, but it’s a personal preference.

So what are the next steps? Ideally we want this available over the internet so that it can receive messages when we’re out and about and not just connected to the same network as the server. That requires a bit of setup and some thought about security, and it’s something I’ll talk about in a future post.

As for the practical uses, they’re pretty much unlimited. Why use IFTTT when we can do it ourselves?

in Home Automation

Related Posts