Wednesday, February 17, 2021

Just A Bit Overengineered: A JavaScript Based, MQTT Powered, iPad Love Note System

The Inspiration: Itty Bitty Sidekick Screens

A few months ago, on a trip to to Best Buy I found myself impressed with their prices tags. Not their prices, but the tags themselves. Apparently, Best Buy replaced old school plastic tags with E-Ink displays. I left that store wondering if I could get my hands on my own little E-Ink display and use it to power a project.

Fast forward to this last weekend where I read about two more e-ink based projects: an Always On E-Ink Org Agenda and a Literary Clock Made form an E-reader. The second project is especially interesting because it describes repurposing an old Kindle rather than building an e-ink project from scratch.

I didn't have a Kindle lying around, but I did have an iPad that wasn't getting much use. It wasn't an e-ink display, but I wondered if it could stand in for one.

And then Valentines Day arrived and I realized what I could use a sidekick screen for: as a message board for leaving love notes to my beloved.

Did I need to turn an iPad into the equivalent of a digital Post-It note? Uh yes, yes I did.

Wait a Minute, Didn't I Just Do This project?

I just got done building PimgStack a project to recycle hardware by using my phone to deliver messages to a device that would display said messages on screen. Isn't this the same thing, but instead of using a Raspberry Pi I'm using an iPad, and instead of delivering images I'm delivering love notes? Yes and yes.

So if they're basically the same project, I found myself wondering if I could recycle any code to make my iPad project come together faster.

Powering an iPad Love Note Delivery System

What made PimgStack work was the message delivery mechanism, MQTT. This left me wondering how I could push MQTT messages to an iPad, and once they arrived, how I could react to them. I got an important clue when I setup the MQTT broker on Amazon's MQ service. Check this out:

Amazon's MQ service provides multiple connection points that talk different protocols. In my Raspberry Pi project I made use of MQTT. A quick Google Search revealed that 'wss' is the Secure Web Sockets protocol. I'd never used Web Sockets, but I figured they must be built into the latest version of Safari running on the iPad.

The Plan: Web Sockets talking to Amazon MQ

If I could write a web page that opened up a Web Socket to talk to Amazon MQ's WSS endpoint, then I'd be home free. It could listen on the socket for messages and when they arrived, render the message in HTML. The page would then repeat the process, waiting for another message to arrive.

I whipped up a quick web page, attempted to open up a WebSocket using the WSS URL and ... nothing. What I'd hoped would Just Work, didn't. As I Googled around, I started to get the impression that it wasn't possible to just connect up to a WSS URL from plain JavaScript.

Fortunately, I kept digging and eventually found Paho.MQTT, a library for bridging WebSockets and MQTT. I updated my simple HTML page to pull in the Paho.MQTT library from this CDN:

  <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>

I then plugged in the WSS host, port, username and password from the Amazon MQ connection area into this code:

var client = new Paho.MQTT.Client(Env.host, Env.port, Env.path, Env.clientId);

client.onMessageArrived = function(m) {
  console.log("Message arrived!", m);
};

client.connect({
  userName: Env.username,
  password: Env.password,
  useSSL: true,
  mqttVersion: 3,
  onFailure: function(e) {
    console.log("FAIL!");
  },
  onSuccess: function() {
    console.log("WHoo!");
    client.subscribe(Env.topic);
  }
});

After punching a hole in the security group to allow 61619, I found that the socket would successfully connect. I wrote a quick Tasker action using the same MQTT Client that I used in my last project, and sent off a message. And Bam! the message was received on the iPad. It was like magic. Damn Paho.MQTT is cool.

I updated the code above to render the message in HTML, picked a sexy font from Google Fonts and made sure to set the meta tag apple-mobile-web-app-capable. The result is a full screen message board which looks surprisingly polished. As a bonus, emoji seamlessly come through. How cool is that?

I whipped up a quick Tasker action that lets me push text to the iPad. I realized that because this is backed by Tasker, any automation I can imagine on my phone can now use the iPad as a display. Say I want to display my step count on the iPad or the last received text message or last incomning phone number. This would all be pretty easy to do now that I've got the iPad listening on an MQTT channel that Tasker can publish to.

Find the source code that powers the iPad component here. It really is amazing how much functionality you can get out of a little plain HTML web app.

Now if you'll excuse me, I need to go compose sweet nothings to my wife.

No comments:

Post a Comment