I’ve been experimenting with invoking services on one machine from another. None of these machines have been mainframes. They’ve been iPads, iPhones, Macs and Raspberry Pis.
I’ve used the plural but the only one actively dualed is iPhone. And that plays a part of the story.
For the purpose of this post you can view iPads and iPhones the same.
Actually mainframers needn’t switch off – as some of this might be a useful parallel.
Why Would You Invoke Services On Another Machine?
It boils down to two things, in my view:
- Something the other machine has.
- Something the other machine can do.
I have examples of both.
At this point I’m going to deploy two terms:
- Heterogeneous – where the architecture of the two machines is different.
- Homogeneous – where the architecture of the two machines is the same.
You can regard Pi calling iOS as heterogeneous. You can regard iOS calling iOS as homogeneous. there is quite a close relationship between these two terms and the “has” versus “can do” thing. But it’s not 100% true.
On “has” I would probably only invoke a service on another device of the same type of it had something that wasn’t on the invoking machine. Such as a calendar. So, for example, I could copy stuff from my personal calendar into my work calendar.
On “can do” I would invoke a service on another machine of a different type of it can do something the invoking machine can’t do. For example, a Raspberry Pi can’t create a Drafts draft – but iOS (and Mac) can.
But Pi can do a lot of things iOS can do, and vice versa. So sometimes “has” comes into play in a heterogeneous way. (I don’t have a good example of this – and it’s not going to feature any further in this post.)
Now let’s talk about some experiments – that I consider “Production-ready”.
Automating Raspberry Pi With Apache Webserver
There are certain things Raspberry Pi – which runs Linux – can do that iOS can’t. One of them is use certain C-based Python libraries. One I use extensively is python-pptx – which creates PowerPoint presentations. My Python code uses this library to make presentations from Python. Normally it would run on my Mac.
At 35,000 feet I can run my Pi on a battery and access it on a Bluetooth network. I can SSH in from my iPad and also have the Pi serve web pages to the iPad.
So I don’t need to pull out my nice-but-cumbersome Mac on a plane.
SSH is my method of choice for administering the Pi. But what of invoking services? Here’s where Apache (Webserver) comes in handy. It’s easy to get Apache with PHP up and running. In my case I use URLs of the form http://pi4.local/services/phpinfo.php
to access it from iOS:
- I can use the Safari web browser.
- I can use a Shortcuts action to GET or POST. In fact all http verbs.
- I can write JavaScript in Scriptable to access the webserver.
- and so on.
Here’s a very simple PHP example:
<?PHP phpinfo(); ?>
I’ve saved this as phpinfo.php in /var/www/html/services on the Pi. So the URL above is correct to access it.
I don’t want to get into PHP programming but the first and the last line are brackets around PHP code. Outside of these brackets could be HTML, including CSS and javascript. phpinfo()
itself is a call to a built in routine that gives information about the PHP setup in the web server. (I use it to validate PHP is even installed properly and accessible from the web server.)
The point of this example is that it’s very simple to set up a web server that can execute real code. PHP can access, for example, the file system.
Here’s another example:
<?php print("<table>\n"); print("<th><td>Parameter</td><td>Value</td></th>\n"); foreach ($_GET as $key => $value) { print("<tr><td>$key</td><td>$value</td></tr>\n"); } print("</table>\n"); ?>
This is queryString.php and it illustrates one more important point: You can pass parameters into a script on the Pi, using the query string portion of the URL. This example tabulates any passed in parameters.
So the net of this is you can automate stuff on the Raspberry Pi (or any Linux server or even a Mac) if you set it up as a web server.
Automating iOS With Shortcuts And Pushcut Automation Server
Automating an iOS device from outside is rather more difficult. There are several components you need:
- Shortcuts – which is built in to both iPad OS and iOS.
- A way to automatically kick off a shortcut from another device.
- Some actual shortcuts to do the work.
Most people reading this are familiar with items 1 and 3. Most people won’t, however, know how to do item 2.
This is where Pushcut comes to the rescue. It has an experimental Automation Server. When I say “experimental”, Release 1.11 three weeks ago from the time of writing introduced it as “experimental” but there have been enhancements released since then. So I guess and hope it’s here to stay, with a few more enhancements perhaps coming.
Before I go on I should say some features of Pushcut require a subscription – but it’s not onerous. I don’t know if Automation Server is one of them – as I happily subscribed to Pushcut long before Automation Server was a thing. There’s a lot more to Pushcut than what I’m about to describe.
When you start up Automation Server it has access to all your Shortcuts, ahem, shortcuts. You can invoke one using a URL of the form
https://api.pushcut.io/<my-secret>/execute?shortcut=Hello%20World&input=Bananas%20Are%20Nice
The input parameter is the shortcut’s input parameter. You don’t have to have an input parameter, of course so just leave off the Bananas%20Are%20Nice
part. (Notice it is percent encoded, which is easy to do, as is the shortcut name.)
The above invokes a (now obsolete version of my) Hello World
shortcut. Obsolete because it now turns the input into a dictionary.
JSON is passed in thus:
https://api.pushcut.io/<my-secret>/execute?shortcut=Hello%20World&input={"a":"123%20456,789"}
Again it’s percent encoded.
On Pi (via SSH from Mac) you can use the Lynx textual browser, wget, or curl. Actually, on Mac, you can do it natively – if you want to.
When you use the URL Pushcut – via the web – invokes the Automation Server on your device. “Via the web” is important as you can’t use the Automation Server technique without Internet access. You can, however, use another function of Pushcut – Notifications-based running of a shortcut.
Curl Invocation
Curl invocation is a little more complex than invoking using a web browser. Curl is a command line tool to access URLs. Here is how I invoke the same shortcut, complete with a JSON payload
curl -G -i 'https://api.pushcut.io/<my-secret>/execute' --data-urlencode 'shortcut=Hello World' --data-urlencode 'input={"a":"123 456,789"}'
Note the separation of the query string parameters and their encoding. I found this fiddly until I got it right.
An Automation Server
It’s worth pointing out that Automation Server should run on a “dedicated” device. In practice few people will have these. So I’ve experimented with what that actually means.
First, buying a secondhand device that is good enough to run iOS 12 (the minimum supported release and not recommended) is prohibitive. In the UK I priced them above £100 so I’d have to have a much better use case than I do.
Second, I don’t have a spare device lying around.
But I do have a work phone (that I donated, actually) that rarely gets calls. It does get notifications but those don’t seem to stop Automation Server from functioning just fine.
So this approach might not be available to many people.
Automating Drafts From Raspberry Pi
One good use case is being able to access my Drafts drafts from my Raspberry Pi. Drafts is an excellent environment for creating, storing and manipulating text. I highly recommend it for iPhone, iPad and Mac users. Again a well-worth-it subscription could apply.
So, my use case is text access on the Pi. I might well create a draft on iOS from the Pi, perhaps storing some code created on the Pi.
So I’ve written shortcuts that:
- Create a Drafts draft.
- Retrieve the UUIDs (identifiers) of drafts that match a search criterion. (In the course of writing this post I upgraded this to return a JSON array of UUID / draft title pairs.)
- Move a draft to the trash (as the way of deleting it).
Here’s what the first one of these looks like:
It’s a simple two action shortcut:
- Create the draft.
- Return the UUID (unique ID) of the newly created draft.
The second action isn’t strictly necessary but I think there will be cases where the UUID will be handy. For example, deleting the draft requires the UUID. So this action returns the UUID as a text string.
The first action is the interesting one. It takes the shortcut’s input as the text of the draft and creates the draft. Deselecting “Show When Run” is important as otherwise the Drafts user interface will show up and you don’t want that with an Automation Server. (It’s likely to temporarily stall automation.)
So this is a nice example where iOS can do something Raspberry Pi (or Linux) can’t. This is not a Mac problem as Drafts has a Mac client.
Outro
A couple of other things:
I did a lot of my testing on a Mac – both directly as a client and also by SSH’ing into the Pi. (Sometimes I SSH’ed into the Pi on both iPad and iPhone using the Prompt app.)
By the way, the cultural allusion in the title is to Depeche Mode’s Master And Servant. I’ve been listening to a lot of Depeche Mode recently.
I’ve titled this section “Outro” rather than “Conclusion” because I’m not sure I have one – other than it’s been a lot of fun playing with one machine calling another one. Or playing Master and Servant. 🙂
One thought on “Let’s Play Master And Servant”