Home

You’re Doing That Wrong is a journal of various successes and failures by Dan Sturm.

Remote Screen Sharing Automation

I’ve always found it fairly easy to manage my multiple Macs with tools like Dropbox, the Mac App Store, and iCloud. But trying to manage Macs that are in different physical locations, on different networks, has really put some of my workflows to the test. There are, it seems, some workflow issues that can’t solved by just putting things in Dropbox. Go figure 1 .

For the past few weeks, I’ve been looking around for ways to “get to” my home iMac from my iMac at work. I quickly found I needed more than just “access to the data” on that computer. I needed to control it via some form of screen sharing.

I tried Screens . It didn’t like my company’s port mapping. Nothing I can really do about that.

Someone in our IT department recommended Royal which, according to my research, is an application that does…something.

In true You’re Doing That Wrong fashion, the solution that had the most success was texting my wife at home and asking her to click “Accept” on the iMessage Screen Sharing request that I was sending from my work computer. But after about a half-dozen requests, I knew I needed a better solution.

Solutioneering

The Screen Sharing tools built into iMessage are great. They’re simple, easy to use, and (miraculously) they just work. I don’t need to open ports on my router or run a private VPN, I just open iMessage, select the person I want to Screen Share with, and click “Ask to Share Screen”.

Given my propensity for making very bad, very unsafe automations, you may be imagining that I just created a Keyboard Maestro macro that would watch for the “Incoming Screen Sharing Request” notification and click “Accept”. But even I realized what an awful idea that would be.

Luckily, there’s another menu item in iMessage, just above the “Ask to Share Screen” item. It’s the “Invite to Share My Screen” option. So, I set about making a tool that I could activate remotely, that would call me from my home iMac and offer to share its screen.

Shortcuts & Hazel

The easiest way to get things up and running was to duplicate a few of the things I’d created for my Open on Which Mac tool. I duplicated the iOS Shortcut I’d use to trigger the whole thing, and the Hazel rule watching for the Shortcut’s input.


  1. Sometimes Dropbox is the issue. But that’s a post for another time. ↩
 
 

The only thing I needed to change in the Shortcut and Hazel rule was to swap “URL” for “ScreenShare” in the filename. So, the Destination Path in the shortcut reads: Applications/Batch/openonmac/Dictionary Value-ScreenShare-Current Date.txt .

While I’m currently only going to use the tool to remote into my home iMac from work, leaving the rest of the Shortcut intact will allow me to more easily 2 add the ability to remote into other computers later.

Keyboard Maestro

Now on to the meat of the thing. We start by using the macOS URL scheme for Messages.app to send a message to my Apple ID. By hard-coding my Apple ID into the macro, there’s no way I can accidentally send the invitation to someone else. Which would be very bad.

By opening the url imessage:myappleid@email.com , KM will open Messages.app and create a new iMessage to my Apple ID. Now, it turns out, it’s not enough to just create a new message with a recipient selected. The Screen Sharing menu items aren’t accessible until you actually send something. So I took this as an opportunity to add a bit of transparency to the process. The macro types out the words “Incoming Connection from Dan’s iMac” and hits Return . In addition to making the Screen Sharing tools accessible, I will get an iMessage (everywhere) letting me know that the Screen Sharing Invitation is imminent and it’s coming from the computer I expected.

Next, the macro opens the “Buddies” menu and selects “Invite to Share My Screen”. Within a few seconds, wherever I may be, and invitation to share the screen of my home iMac appears on my desktop and I can click “Connect”.


  1. With one potentially major hurdle. ↩

That was…surprisingly simple.

Not quite

Since Apple is very good about keeping things safe and secure, the Screen Sharing session activates in “Observing” mode. Which is not terribly helpful. Additionally complicating matters, the only way to approve “Control” of the Screen Sharing session to a remote user is to click on the Screen Sharing menu bar icon that indicates a connection is active.

Initially, I tried to click the menu with Keyboard Maestro’s “Click at Found Image” action, but the menu bar icon flashes when connected and it failed more often than it succeeded. After a bit of googling, some poking around in Activity Monitor, and a brief consultation with Dr. Drang , I discovered I could activate the menu and select “Allow Dan to control my screen” with some basic AppleScript. Which looks like this:

tell application "System Events" to tell process "SSInvitationAgent"
    click menu bar item 1 of menu bar 1
    click menu item 2 of menu 1 of menu bar item 1 of menu bar 1
end tell

Limitations and Improvements

There is one big limitation to this tool. You may have already guessed it. The tool, as it exists here, doesn’t work when the computer is locked. So I resorted to turning off “Require Password” in System Preferences on my home iMac. Which sounds like a huge security risk not worth taking for the benefit it provides but, frankly, if an untrustworthy person is sitting at my desk in my home office, I have bigger problems than whether or not there’s a password on my iMac.

This does, however, preclude me from using this particular solution for the reverse procedure of connecting to my work iMac from home. Turning off my system password definitely isn’t going to fly with our IT department. So, at the moment, this is at best half a solution.

Another thing I’ll probably change in the next iteration of the tool is to remove Hazel from the process entirely. Recently, in the process of debugging a Hazel rule, I recreated it from scratch inside Keyboard Maestro. KM’s ability to watch a folder and act on files that appear inside worked well enough for me to consider migrating more “watch folder” actions over there in the future. Its debugging tools are better, too.

Something else that could use improving is the speed of some of the actions. Currently, depending on how long it takes for me to accept the screen sharing session from my work iMac, the screen sharing menu bar icon may not be available in time for the AppleScript action to find it and grant me “Control” access. My current workaround is to just run the whole process again while I’m in “Observe” mode. It only takes a few second and it works fine.

Speaking of the AppleScript step, there’s also an odd delay of a few seconds between opening the menu bar app and selecting the “Allow Dan to Control” item. In my conversation with Dr. Drang, he pointed me to this post on Stack Overflow which both explained and solved the issue, so that seems like an easy fix for the next version.

By the way, it would seem (to me) that none of this would need to exist if there was some mechanism by which iMessage could tell that the Screen Sharing request was coming from my Apple ID, sent to my Apple ID, and allow me to automatically authenticate those interactions. Hell, prompt me for my iCloud password if you want to keep it safe. Seems like a reasonable request to me, but what do I know. I’m just some idiot with a blog.

Open the Doors

If my penchant for removing incredibly specific, minor inconveniences from my life with overly-complicated, home-grown automation tools wasn't yet fully evident, get ready to be dazzled by the lengths to which I go with this one.

It's winter time here in terrible Phoenix, Arizona, and that means temperatures with highs in the high-70s to low-80s, and lows in the mid-40s. Translated: it's a bit too warm to turn on the heater, and a bit too cool to necessitate air-conditioning.

As a result, over the course of a day, the temperature inside our home ranges from 70F in the morning, to upwards of 78F by late afternoon. Since I work at home and I hate feeling hot [3], I like to keep the front and back doors to the house open in the mornings and evenings, in an effort to cool the house enough to keep the mid-day temperatures inside below 75F.

Generally, that means keeping the doors open in the morning until the temperature outside rises above 70F, and keeping them closed until the temperature drops back down below 70F in the evening.

"I don't see the problem," you say. "Just shout at Siri or your Echo Dot and ask the temperature periodically. Or just look down at your Apple Watch. Or literally any number of other options at your disposal."

Yes, I totally hear you.

Now, take a deep breath because it's going to get weird.

Most weather services use a weather station downtown or at the airport of your city. In my case, those weather stations are 25 miles away and on the other side of a very large mountain. The result being that they're almost always wrong for my neighborhood by about 3 or 4 degrees.

So, I primarily monitor the temperature with a Weather Underground station located less than a half-mile from my home. I keep the WU widget in my Today view on my phone and periodically swipe over, scroll down, and wait for it to update. I love a lot of things about Weather Underground. The speed at which its app refreshes is definitely not one of them. In fact, I usually end up launching the app from the widget in order to make sure it's actually refreshed and not showing me old data. And don't even get me started on its Apple Watch complication. It's tiny and ugly and I hate it.

Are you still reading? Okay, good.

Unrelated to the weather, I've recently begun playing around with Pushover on iOS to send myself custom push notifications based on whatever criteria I deem worthy of a notification. It's super simple to set up and use, has a ton of flexibility, and does exactly what you'd expect it to do. I love it.

I've heard of people using it to alert themselves when a long video render has completed so they can go about their day without needlessly checking the progress bar on their computer. A very cool use case that I will definitely investigate. But, on this morning, I thought to myself, how cool would it be if I could set up Pushover to send me a notification when the temperature at my local WU station goes above / drops below 70F?

To the WU

In addition to being a very cool service, Weather Underground has a nice developer API. You can sign up for a free developer account that will let you to request Current Conditions up to 500 times per day. That's more than enough for what I want to do.

With a simple call of:

curl http://api.wunderground.com/api/DEVELOPERID/conditions/q/AZ/pws:EXAMPLESTATION.json

I get a return like this:

{
  "response": {
  "version":"0.1",
  "termsofService":"http://www.wunderground.com/weather/api/d/terms.html",
  "features": {
  "conditions": 1
  }
    }
  ,    "current_observation": {
        "image": {
        "url":"http://icons.wxug.com/graphics/wu2/logo_130x80.png",
        "title":"Weather Underground",
        "link":"http://www.wunderground.com"
        },
        "display_location": {
        "full":"Phoenix, AZ",
        "city":"Phoenix",
        "state":"AZ",
        "state_name":"Arizona",
        "country":"US",
        "country_iso3166":"US",
        "zip":"XXXXX",
        "magic":"1",
        "wmo":"99999",
        "latitude":"33.XXXXXX",
        "longitude":"-112.XXXXXX",
        "elevation":"373.1"
        },
        "observation_location": {
        "full":"Example Station, Phoenix, Arizona",
        "city":"Example Station, Phoenix",
        "state":"Arizona",
        "country":"US",
        "country_iso3166":"US",
        "latitude":"33.XXXXXXX",
        "longitude":"-112.XXXXXX",
        "elevation":"1214 ft"
        },
        "estimated": {
        },
        "station_id":"EXAMPLESTATION",
        "observation_time":"Last Updated on February 6, 11:46 AM MST",
        "observation_time_rfc822":"Tue, 06 Feb 2018 11:46:53 -0700",
        "observation_epoch":"1517942813",
        "local_time_rfc822":"Tue, 06 Feb 2018 11:47:00 -0700",
        "local_epoch":"1517942820",
        "local_tz_short":"MST",
        "local_tz_long":"America/Phoenix",
        "local_tz_offset":"-0700",
        "weather":"Clear",
        "temperature_string":"72.4 F (22.4 C)",
        "temp_f":72.4,
        "temp_c":22.4,
        "relative_humidity":"21%",
        "wind_string":"From the SE at 1.0 MPH Gusting to 3.0 MPH",
        "wind_dir":"SE",
        "wind_degrees":139,
        "wind_mph":1.0,
        "wind_gust_mph":"3.0",
        "wind_kph":1.6,
        "wind_gust_kph":"4.8",
        "pressure_mb":"1014",
        "pressure_in":"29.95",
        "pressure_trend":"-",
        "dewpoint_string":"30 F (-1 C)",
        "dewpoint_f":30,
        "dewpoint_c":-1,
        "heat_index_string":"NA",
        "heat_index_f":"NA",
        "heat_index_c":"NA",
        "windchill_string":"NA",
        "windchill_f":"NA",
        "windchill_c":"NA",
        "feelslike_string":"72.4 F (22.4 C)",
        "feelslike_f":"72.4",
        "feelslike_c":"22.4",
        "visibility_mi":"10.0",
        "visibility_km":"16.1",
        "solarradiation":"--",
        "UV":"4","precip_1hr_string":"0.00 in ( 0 mm)",
        "precip_1hr_in":"0.00",
        "precip_1hr_metric":" 0",
        "precip_today_string":"0.00 in (0 mm)",
        "precip_today_in":"0.00",
        "precip_today_metric":"0",
        "icon":"clear",
        "icon_url":"http://icons.wxug.com/i/c/k/clear.gif",
        "forecast_url":"http://www.wunderground.com/US/AZ/Phoenix.html",
        "history_url":"http://www.wunderground.com/weatherstation/WXDailyHistory.asp?ID=EXAMPLESTATION",
        "ob_url":"http://www.wunderground.com/cgi-bin/findweather/getForecast?query=33.XXXXXX,-112.XXXXXX",
        "nowcast":""
    }
}

It's a lot, I know. But it includes everything we would ever want to know about our hyper-local weather station. Including the current temperature, after the value labled temp_f. With a quick REGEX, we can search through this response and pull out just the current temperature in Fahrenheit.

That REGEX looks like this:

(?<="temp_f":)(.*?)(?=,)

The Push

Once we've determined our current temperature is above 70.0F, we'll send ourselves a notification with Pushover by running a command that looks like this:

curl -s \
  --form-string "token=MY_TOKEN" \
  --form-string "user=MY_USERID" \
  --form-string "message=It's above 70F outisde." \
  --form-string "title=Close the Doors" \
  https://api.pushover.net/1/messages.json

Which pops up on my iPhone and Apple Watch looking like this:

The Push Notification from Pushover

The Push Notification from Pushover

Workflow, Assemble

To put all these pieces together, I turn once again to my beloved Keyboard Maestro. Since I'm sending 2 push notifications over the course of the day, I set up 2 macros with different trigger criteria.

Our "Morning" macro doesn't need to start pinging the weather station at 12:01AM, and it won't need to keep checking into the afternoon, so I set it to start, every day, at 6:30AM and stop at 1:00PM. When it stops, the "Evening" macro starts. It begins checking at 1:00PM and stops at Midnight.

While running, each macro requests the current conditions from the weather station every 5 minutes (300 seconds); well under the 500 requests per day we're allowed with our free developer account. Once the temperature reaches 70.0F, the macro ends the loop, sends the push notification, and restarts the next day.

Here are both the Morning and Evening macros:

The Morning Macro in Keyboard Maestro

The Evening Macro in Keyboard Maestro

Why did you do this and why did I just read that?

Truth be told, I'll probably only get 2 or 3 months of usage from this thing each year. Soon, the temperature will be above 70F all day and night and our monthly air-conditioning bill will cost as much as an iPad.

But, until then, this tool is a delightful aide in my quest to stay cool at home, and it was a fun way to explore the Weather Underground and Pushover APIs.

Plus, I haven't posted anything to this blog in a while and I hear that's bad. So.


  1. No, the irony of where I live does not escape me.  ↩

Twitter Advanced Search Keyboard Maestro Macro

I enjoy using Twitter. I do not enjoy using Twitter.com in a web browser.

On occasion, I recall a conversation that I'd like to find again. Twitter provides a pretty great set of search tools at https://twitter.com/search-advanced but, again, the website experience is pretty awful, on the whole.

Lucky for us, the Twitter Advanced Search tools are just a GUI for a pretty straightforward URL scheme. With the help of Keyboard Maestro, we can skip the ugly web search front end and jump right to the results. A much more pleasant experience.

Asterisks

I left out the date search tools because I rarely find them useful and there isn't a great way to recreate them in KM. The only other minor annoyance with the macro is the speed. It pastes the encoded variables into the Safari address bar in chunks, as it processes. I wouldn't call it slow, but it's not as quick as it would be if the entire URL were encoded before being pasted.

Here's where I'd normally put a screenshot of the macro in Keyboard Maestro but, frankly, it's absurdly long so just download it and take a look for yourself.

Open Last QuickTime File Macro

Yesterday, Dr. Drang had a nice post about creating a keyboard shortcut for the Open Recent menu item in BBEdit using Keyboard Maestro. I purchased Keyboard Maestro a few months ago and have been meaning to find some time to play with it. I’ve also been meaning to find a way to open the most recently viewed video in QuickTime with a global keyboard shortcut. Let’s skip right to the punchline.

KM_Macro_Cropped.png

Throughout the course of a project, I spend a lot of time referring to the most recent cut of a video alongside notes from the client. Once I know the next shot or note I’m going to address, I close the cut, my notes, and get to it. Since my notes live in nvALT, they disappear and reappear with a quick ⌃Z. Now, no matter what I’m doing, I can quickly summon the video file with a keyboard shortcut as well.

A simple tool that removes way more friction that you’d probably guess. It’s a good thing.