And now it’s all this http://www.leancrew.com/all-this I just said what I said and it was wrong. Or was taken wrong. Tue, 02 Sep 2014 03:23:26 +0000 en-US hourly 1 http://wordpress.org/?v=3.9.2 Afghanistan, August 2014 http://www.leancrew.com/all-this/2014/09/afghanistan-august-2014/ http://www.leancrew.com/all-this/2014/09/afghanistan-august-2014/#comments Tue, 02 Sep 2014 03:23:24 +0000 http://www.leancrew.com/all-this/?p=2298 My younger son started high school a couple of weeks ago. He was a year and a half old when this war started. My older son was in preschool at the time. He’s now a senior and will have to register with Selective Service in a couple of months.

For them, we really have always been at war with Eastasia.

Afghanistan, August 2014

]]>
http://www.leancrew.com/all-this/2014/09/afghanistan-august-2014/feed/ 0
Getting around a GMail restriction http://www.leancrew.com/all-this/2014/08/getting-around-a-gmail-restriction/ http://www.leancrew.com/all-this/2014/08/getting-around-a-gmail-restriction/#comments Sun, 31 Aug 2014 05:21:24 +0000 http://www.leancrew.com/all-this/?p=2297 For several years now, I’ve had a script called checkcards that logs into my local library, collects information on the items my family has checked out and on hold, and sends me an HTML email with the information presented in tabular form.

Checkcards message

I have launchd set up on my office iMac to run this script every morning. My wife also gets a copy through a mail rule on the server.

Until recently, this message was generated through a Python script using the mechanize library and then sent from my iMac via the sendmail command. 12 In late July, I noticed that the email from checkcards had stopped. I’m no email routing expert, but it appeared to me that GMail was refusing to deliver messages routed to it from my computer.

This wasn’t a big surprise. If anything, it was more surprising that GMail had ever accepted messages routed to it from an unauthenticated machine like my iMac. Even back in the 90s, the onslaught of spam had caused mail servers to become more restrictive on who they’d route mail for. I remember having to add special settings to the Exim configuration on my Linux box to get around these restrictions.

With sendmail no longer working, I needed a new way to get my messages delivered. I decided to try out Python’s smtplib module, and after a bit of experimenting I found I could send my messages with just a few lines tacked onto the end of the script. Here are the lines:

python:
206:  # Send the message through GMail.
207:  smtp = smtplib.SMTP_SSL('smtp.gmail.com', 465)
208:  smtp.ehlo()
209:  smtp.login(gmailUser, gmailPassword)
210:  smtp.sendmail(mailFrom, mailTo, msg)

Line 207 establishes the connection to the GMail SMTP server on port 465. Line 208 starts the SMTP communication with an EHLO (extended hello) command. Line 209 then logs on using my GMail credentials (established earlier in the script), and Line 210 actually sends the message. It was much simpler than I feared.

If you’re wondering why I don’t use a service like Library Elf, the answer is simple: my library isn’t in the Elf system. Unless you happen to use the Naperville Public Library, my script won’t be of any direct use to you, but it’s on GitHub anyway, on the off-chance that other people can alter it to fit their own needs. If your family uses the library a lot, a centralized system for tracking everything you have checked out can make your life simpler.


  1. Sendmail is the venerable Unix utility for routing email over the network. It’s legendary for its cryptic configuration file and its vulnerabilities. It was Sendmail that allowed the Great Internet Worm of the late 80s to spread. Given how small the internet was back then, “great” is something of an overstatement, but that’s how it was thought of at the time. 

  2. On OS X, the sendmail command doesn’t really run Sendmail, it runs Postfix in Sendmail compatibility mode. 

]]>
http://www.leancrew.com/all-this/2014/08/getting-around-a-gmail-restriction/feed/ 0
Late to Launch http://www.leancrew.com/all-this/2014/08/late-to-launch/ http://www.leancrew.com/all-this/2014/08/late-to-launch/#comments Sat, 30 Aug 2014 06:21:01 +0000 http://www.leancrew.com/all-this/?p=2296 I’m so late to Launch Center Pro. I bought it fairly early on, but never got into using it. Despite the hoopla when it was released, I didn’t understand why I should use an app that basically launched other apps and performed tasks I almost never do, like toggle the screen brightness or turn on the flashlight. I tucked LCP away on one of my never-swipe-to screens and forgot about it. I didn’t pay attention things to Alex Guyot’s encyclopedic guide to LCP or to Phillip Gruneich’s giant list of apps that support x-callback-url because I “knew” LCP wasn’t for me.

I used Drafts, of course. Since much of what I do involves text, it seemed more natural to use actions that start in a text editor. But even with Drafts, I was pretty conservative in my use of actions, because I do most of my real work on a Mac and have focused on creating scripts, macros and other automated workflows that help me there.

Earlier this month I learned what I was missing. After building an overly complicated set of scripts for adding common entries to my work diary, I learned how much simpler a set of LCP actions would be. I now have a color-coded group of actions for all my common diary entries.

Work diary LCP actions

The icons I chose from LCP’s collection may not be the best expression of the concepts, but they were easy to implement and didn’t require any artistic ability on my part. The goal is to have buttons that are distinct enough that I can choose the appropriate one quickly without putting on my reading glasses.

Note that the Diary button itself is in a spot that’s easy to reach with the left thumb. I know that many people hold their phone in their dominant hand, but I’ve never done that. Because I often need my right hand free to take notes, my habit is to have the phone in my left hand.

My other group of actions is for running the scripts that clean up my iPhone screenshots. These are the final versions of scripts that evolved over the course of a couple of months near the end of last year.

iOS screenshot LCP actions

I use color coding to distinguish between the single-image scripts and the pair scripts, and I use icons to distinguish between screenshots taken on WiFi and those taken on LTE. The icon I use for WiFi is actually the RSS icon, and the one I use for LTE is absurdly generic, but they communicate their meaning to me, which is all that counts.

My main LCP screen is pretty sparse.

Main LCP screen

The Scanner button opens JotNot Pro, the app I use for scanning receipts when I’m on the road. It doesn’t do any clever actions; I have it here only because JotNot Pro itself is in a folder on my second screen, so having it here makes it easier to launch.

The Map button opens the Maps app to the address on the clipboard (or it fails miserably if there’s no address on the clipboard). When I arrange a business trip, I put all the pertinent travel information in a plain text file in Dropbox. This includes the addresses of the hotel I’m staying at and any other places I’ll be visiting. When I get in my rental car to drive to one of these locations, I copy its address out of the file and run this action. This may not seem like much of a time-saver—I can, after all, just open Maps and paste in the address—but I’ve found that I often mistap when trying to select the address field in Maps and have to try again. Using the LCP action eliminates the frustration that comes from my clumsiness. The URL for the Map action is

https://maps.apple.com/?q=[clipboard]&lc-icon=maps

The Convert button is sort of an experiment; I don’t think I’ll keep it. It prompts me for a number,

Prompt for number to convert

then launches PCalc to its conversions section. The URL for the Convert action is

pcalc://convert/[prompt-num:Number]

I don’t think this is actually faster than just launching PCalc from the home screen and tapping the A→B button. I just wanted to try out a PCalc URL scheme and the LCP [prompt-num] option.

With iOS 8 and its extensions just a couple of weeks away, I don’t want to get too deeply into Launch Center Pro. Some of the actions I could make might be better done with an extension. I’ll have to explore both possibilites when I upgrade. Too bad I wasted time up until now that could have been saved with LCP actions.

]]>
http://www.leancrew.com/all-this/2014/08/late-to-launch/feed/ 0
Energy dissipation in damped vibrations http://www.leancrew.com/all-this/2014/08/energy-dissipation-in-damped-vibrations/ http://www.leancrew.com/all-this/2014/08/energy-dissipation-in-damped-vibrations/#comments Wed, 27 Aug 2014 23:21:00 +0000 http://www.leancrew.com/all-this/?p=2295 In the previous post in this series (which was four months ago—time flies), we looked at the free vibrations of damped single-degree-of-freedom (SDOF) systems, systems that can be modeled as a spring-mass-dashpot like this:

Spring-mass-damper

The position of the mass, [u], can be expressed as a function of time, [t], through the formula

[u = A e^{-\zeta \omega_n t} \cos (\omega_d t - \phi)]

where [\omega_n] is the natural frequency of the undamped system, [\omega_d] is the frequency of the damped system, and [\zeta] is the damping ratio. They’re related to the physical properties of the system through these equations:

[\omega_n = \sqrt{\frac{k}{m}}] [\zeta = \frac{c}{2 m \omega_n}] [\omega_d = \sqrt{1 - \zeta^2} \omega_n]

The other two variables, [A] and [\phi], are determined through the initial position and velocity of the mass. As discussed before, we can start our clock at any time we like; we can, without any loss of generality, set [t = 0] at a point that will lead to [\phi = 0]. This simplifies the solution to

[u = A e^{-\zeta \omega_n t} \cos \omega_d t]

Taking the derivative of [u] gives us the velocity:

[\dot u = -A \omega_n e^{-\zeta \omega_n t} \left( \zeta \cos\omega_d t + \sqrt{1 - \zeta^2} \sin \omega_d t \right)]

where we’re using Newton’s dot notation for derivatives with respect to time.

In an earlier post, we calculated the total mechanical energy of an undamped system and showed how it remains constant over time. Let’s look at the mechanical energy of our damped system. The potential energy is

[U = \frac{1}{2} k u^2 = \frac{1}{2} k A^2 \left[ e^{-\zeta \omega_n t} \cos \omega_d t \right]^2]

and the kinetic energy is

[T = \frac{1}{2} m \dot u^2 = \frac{1}{2} m \omega_n^2 A^2 \left[ e^{-\zeta \omega_n t} \left( \zeta \cos\omega_d t + \sqrt{1 - \zeta^2} \sin \omega_d t \right) \right]^2]

Because [k = m \omega_n^2], the kinetic energy can also be written as

[T = \frac{1}{2} k A^2 \left[ e^{-\zeta \omega_n t} \left( \zeta \cos\omega_d t + \sqrt{1 - \zeta^2} \sin \omega_d t \right) \right]^2]

The total mechanical energy is the sum of these two, [U + T]. Instead of giving it as a long formula, let’s plot it. We’ll have to choose a particular damping ratio, so let’s go with [\zeta = 0.10].

Damped vibration energy balance

Note how the total mechanical energy decreases with time. Where is it going? It’s being dissipated as heat as the fluid in the dashpot gets pushed back and forth by the piston. The total energy curve is wavy because the activity of the dashpot changes with time. When the mass is near the extreme left and right ends of its travel (when [\omega_n t \approx 0, \pi, 2\pi, …]), its velocity is nearly zero and the dashpot isn’t doing much. The total energy is nearly constant during these times. On the other hand, when the mass is moving quickly (when [\omega_n t \approx \pi/2, 3\pi/2, 5\pi/2, …]), the dashpot is at its peak of activity and the total energy drops rapidly.


At the end of the previous post, I questioned the usefulness of analyzing a spring-mass-dashpot system:

Mechanical systems have springy parts and they have mass, but very few have actual dashpots. What good is all this math if it doesn’t represent actual equipment? We’ll talk about the kinds of real-world things we model as dashpots next time.

We model systems using dashpots because that leads to differential equations that we can solve. What we model as dashpots are things that dissipate mechanical energy from the system. For example:

  • Sliding friction
  • Material damage and flow
  • Hysteresis

Sliding friction is very common—almost unavoidable. It occurs at joints where parts are supposed to move relative to one another, like hinged joints; but it also occurs at joints where the part aren’t supposed to move relative to one another, like bolted joints. Surfaces held together by bolts are supposed to remain fixed, but they slide anyway—a little bit, back and forth—as the machine or structure vibrates. This slippage causes the parts to heat up, and it’s that transformation of mechanical energy into heat that causes the total mechanical energy of the system to decrease

Materials deformed beyond their elastic limit cannot spring back to their original state, leading to a loss of mechanical energy. Energy is also consumed when cracks form in a material because it takes energy to create the new surfaces on either side of a crack. This is a very common mechanism for energy dissipation in concrete structures.

Both plastic deformation and cracking are forms of hysteresis, but hysteresis also occurs anytime the loading and unloading curves of a material don’t match up.

Hysteresis

Image from Wikipedia.

The energy lost during a cycle of loading and unloading is represented by the area between the two curves. Hysteresis can occur in metals even when they’re loaded below the elastic limit, especially when the loading is rapid.

None of these dissipation mechanisms match the dashpot mathematically—that is, the energy loss wouldn’t follow perfectly the wavy curve shown in the energy plot. But we can choose a value of [\zeta] that makes the total energy loss the same, and that’s often good enough. Engineering is not science. The goal of engineering is not to understand our systems perfectly (which we could never achieve); the goal is to understand them well enough to build devices that work.

]]>
http://www.leancrew.com/all-this/2014/08/energy-dissipation-in-damped-vibrations/feed/ 0
It’s just a silly phase I’m going through http://www.leancrew.com/all-this/2014/08/its-just-a-silly-phase-im-going-through/ http://www.leancrew.com/all-this/2014/08/its-just-a-silly-phase-im-going-through/#comments Tue, 26 Aug 2014 01:46:37 +0000 http://www.leancrew.com/all-this/?p=2294 I saw Guardians of the Galaxy this past weekend and really enjoyed it. There were a few clunky spots, and I have no idea why people are praising Vin Diesel’s voicing of Groot,1 but it was a fun movie. The movie was not, however, about my Guardians of the Galaxy.

Here are my Guardians, straight outta 1975:

Guardians of the Galaxy

Steve Gerber wrote the Guardians stories during my comics collecting days. I was a big Gerber fan back then, and read everything of his I could get my hands on. I have no idea what Marvel plans to do with Howard the Duck, but (Spoiler Alert!) I assume his appearance at the end of the movie was a nod to Gerber’s work on the old Guardians. Or maybe it was just a recognition that a racoon wasn’t the first anthropomorphic animal hero.

One of the old Guardians did make it into the movie. See the blue-skinned guy with the red fin coming out of his head? That’s Yondu, he of the whistle-controlled yaka arrows. Same blue skin but with a bar on top of his head instead of a fin. And the comic book Yondu didn’t have Michael Rooker’s menacing southern accent, probably because he was from Centauri IV.

The token Earthling, Vance Astro2 (in the blue and white outfit), like Peter Quill, left Earth in 1988, but he wasn’t abducted. Astro volunteered. He was put in suspended animation, bundled into a rocket, and shot to Alpha Centauri in a poorly thought-out attempt to save the human race. In the 1988 of 1975, we were all dying of cancer because we’d destroyed the ozone layer.3 How was one man alone supposed to start a colony on another world? Beats the hell out of me.

Marvel didn’t even think to give Astro an awesome mixtape, because predicting rockets to Alpha Centauri was easier than predicting the Walkman. You’d think they could’ve at least given him an 8-track player.


  1. Bradley Cooper’s Rocket Racoon, on the other hand, deserves every bit of acclaim it’s received. 

  2. Yes, Vance Astro. 

  3. As I recall, Marvel used ozone depletion to explain Killraven’s future Earth, too. 

]]>
http://www.leancrew.com/all-this/2014/08/its-just-a-silly-phase-im-going-through/feed/ 0
Better work diary actions http://www.leancrew.com/all-this/2014/08/better-work-diary-actions/ http://www.leancrew.com/all-this/2014/08/better-work-diary-actions/#comments Mon, 25 Aug 2014 03:37:47 +0000 http://www.leancrew.com/all-this/?p=2293 In the update at the beginning of this post that shouldn’t have been written, I show how the Launch Center Pro work diary actions should have been built, but I’d like to have a freestanding post describing the actions that I can refer to later. This will be that (somewhat redundant) post.

The LCP actions I use for common entries in my work diary leverage the Drafts action I first described in this post.

Drafts work diary action

This action takes the current time and the contents of the active draft and appends it to a Dropbox file named for the current day. It differs slightly from the original version of the action in that I now use a 24-hour clock for the timestamps.

The diary file that results looks something like this:

07:22
Leaving home

08:05
At site

09:13
Leaving site

09:58
At office

Because it’s in Dropbox, I can refer to it from any device.

My most common entries have to do with travel, so I created a set of Launch Center Pro actions to make those entries with a single tap/swipe. They’re in an LCP group entitled Diary:

LCP work diary group

Each action is defined in pretty much the same way. Here’s the one for Leaving Home:

Launch Center Pro diary action

The URL is this:

drafts://x-callback-url/create?text=Leaving%20home&action=Work%20diary&x-success=launch%3A

The only difference between the various diary entry actions is the text= part. The x-success portion at the end causes my screen to return to LCP when the action is done.

I switched to these simple actions from my messy Pythonista scripts on the suggestion of David Cross. Had I waited a little longer, I could’ve just copied an action written by Greg Pierce instead of writing them from scratch. Still, it was heartening to see that what I came up with was basically the same as Greg’s example—that meant I’d finally done it right.

I do think, though, that I can improve the actions a bit. Not by editing the URLs, but by customizing the icons. Because they’re all currently using the default icon for Drafts actions, they all look the same except for their titles, which are too small for me if I’m not wearing my reading glasses. I’m going to look around for public domain icons that will make them more distinct.

Update 8/25/14
A few readers have asked about using geofencing to automatically make entries for leaving and arriving at home and work. I thought about doing that as I was making the actions but decided against it. My work diary isn’t meant to be a tool for tracking my life. As popular as that sort of thing is nowadays, I have no interest in it. I use the diary to account for time I can bill my clients and nothing else. You might say that automatically adding entries I can’t bill for doesn’t hurt, but I don’t agree. With my current system, every entry is relevant when I’m generating a bill after a trip; with an automatic system, the great majority of the entries would be irrelevant, and I would waste time sifting through them.

]]>
http://www.leancrew.com/all-this/2014/08/better-work-diary-actions/feed/ 0
Work diary revisited http://www.leancrew.com/all-this/2014/08/work-diary-revisited/ http://www.leancrew.com/all-this/2014/08/work-diary-revisited/#comments Thu, 21 Aug 2014 06:09:20 +0000 http://www.leancrew.com/all-this/?p=2292

Update 8/21/14
You can pretty much ignore this post unless you want to explore the psychology of how someone can get caught in one way of thinking and miss something as plain as the nose on his face.

My first instinct is to write scripts, and I knew I could write Pythonista scripts to do what I wanted. But I didn’t want to have to launch Pythonista to run the scripts, because that would involve a lot of scrolling and would cost more time than they saved. I knew, though, that I could create home screen shortcuts that would run each script with a single tap. You’ll note that there’s no thought of using Launch Center Pro at this point. Although I bought LCP a while ago, I never got into using it.

After making the home screen shortcuts, I found that running a script that way would leave me in Pythonista. Because there’s no URL scheme for Springboard, I couldn’t script in a way to go back to the home screen where the icons lived. I really didn’t want to have to press the home button to get out of Pythonista.

That was when I hit upon using Launch Center Pro, and I was happy because everything worked. But I should’ve realized that LCP, combined with the Work diary action I’d already built in Drafts, could do what I wanted with very simple actions like this:

drafts://x-callback-url/create?text=Leaving%20home&action=Work%20diary&x-success=launch%3A

Not only is this far, far simpler than the Pythonista scripts described below, it runs faster and is more flexible. Later today, I’ll write a much shorter post about using LCP actions like this to create common diary entries.

In the meantime, read what’s below only if you want to look at a case study in complicated foolishness.

The work diary I outlined in this post last year continues to serve me well, but I’ve been looking for more efficient ways to make common entries. After a few attempts that weren’t as helpful as I’d hoped, I think I’ve hit on a solution using a combination of Pythonista and Launch Center Pro.

To review, my work diary is a set of text files stored in a Dropbox folder named “Diary.” Each file is named according to the date, like 2014-08-20.txt, and contains timestamped entries that look like this:

22:06
Started 200 degree test

22:45
Ended 200 degree test

22:54
Started 300 degree test

These entries are created in Drafts. I type or dictate the text of what I’m doing into a blank draft, invoke the Work diary action,

Drafts diary entry

and a new timestamped entry is added to the day file. The Drafts action that does the work is defined this way,

Drafts work diary action

where the file name is

[[date|%Y-%m-%d]]

and the template for the entry is

[[date|%H:%M]]
[[draft]]

This is a slight change from what I started with last year. Back then, the timestamp used a 12-hour clock with an AM/PM marker. I’ve since changed to a 24-hour clock to make it easier to figure out how much time I spent on each activity.

I don’t have the patience or the discipline to track all my time this way, but I have found this system especially useful on days when I travel. On these days, the entries tend to take on a few common forms:

07:22
Leaving home

08:05
At site

09:13
Leaving site

09:58
At office

Because I usually make these entries in my car with the Bluetooth connection on, the ambient noise and car speakerphone make Siri dictation less than perfect. To avoid dictation errors, I set up some shortcuts using the builtin iOS Settings. I soon learned that while shortcuts work fine when they’re part of a longer batch of text, they leave you hanging when the shortcut is the only thing you type.

Shortcut expansion

The little autocorrect bubble just sits there until you either type something else or tap somewhere in the text field.

TextExpander snippets are better for standalone entries because they expand immediately, with no need for additional typing or tapping. So I made a series of snippets for the entries I found myself making again and again.

lhz  -> Leaving home
lwz  -> Leaving work
lsz  -> Leaving site
lhoz -> Leaving hotel
ahz  -> At home
awz  -> At work
asz  -> At site
ahoz -> At hotel

I used these snippets for months, and they never gave me any trouble. Still, it seemed as though the sequence of

  1. Open Drafts
  2. Type abbreviation
  3. Tap action button
  4. Tap Work diary action

was too much for something as routinized as entering canned text like this, especially when my thumbs mistyped the abbreviation and I had to back up and retype. Autocorrect never wanted to turn “adz” into “asz” for me.

So I started thinking about ways to automate these entries further, and Pythonista seemed like my best bet.1 What I ended up with was a series of eight scripts—one for each of the common entries—that I run from Launch Center Pro.

Launch Center Pro shortcuts

A single tap on one of these icons switches me to Pythonista, runs the appropriate script to create a diary entry, and returns to Launch Center Pro. Counting the tap to start LCP itself, that’s two taps to make a diary entry, each on a large target with no chance for mistyping.

The scripts that do the work rely on the Dropbox module that comes with Pythonista. This module is not quite as easy to use as the one described in the Dropbox Python SDK documentation, and unfortunately the Pythonista documentation for the module contains some mistakes, but with a little trial and error I was able to get a set of scripts that worked.

The first step was to go to Dropbox’s App Console and “create an app.” This generated an app key and app secret that I could use to give my scripts access to my Dropbox files. I did that using this script, which is a slight modification of the authorization script in the Pythonista Dropbox documentation:

python:
 1:  from dropbox import client, rest, session
 2:  import clipboard
 3:  
 4:  # Get your app key and secret from the Dropbox developer website
 5:  APP_KEY = 'aaaaaaaaaaaaaaa'
 6:  APP_SECRET = 'bbbbbbbbbbbbbb'
 7:  
 8:  # ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
 9:  ACCESS_TYPE = 'dropbox'
10:  
11:  sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)
12:  
13:  request_token = sess.obtain_request_token()
14:  
15:  url = sess.build_authorize_url(request_token)
16:  
17:  # Make the user sign in and authorize this token
18:  clipboard.set(url)
19:  print "url:", url
20:  print "This URL is on the clipboard. Please visit the website and press the 'Allow' button, then hit 'Enter' here."
21:  raw_input()
22:  
23:  
24:  access_token = sess.obtain_access_token(request_token)
25:  
26:  print 'key:', access_token.key
27:  print 'secret:', access_token.secret
28:  print
29:  client = client.DropboxClient(sess)
30:  print "linked account:", client.account_info()

The APP_KEY and APP_SECRET in Lines 5 and 6 are the strings I got from the Dropbox App Console. Running this script within Pythonista puts a Dropbox authorization URL on the clipboard and then pauses at Line 21. At this point, I went to Safari, pasted the URL, and authorized my app in much the same way I authorized Tweetbot, Storify, Pinboard, and other apps. Returning to Pythonista and the paused script, I tapped the Return key to allow the script to finish. Lines 26 and 27 printed out the access key and secret that are needed in the next script. With that, this script has done its job and is no longer needed.

By the way, the description of obtain_access_token is one of the places where the Pythonista Dropbox module documentation is wrong. It says the return value is a tuple of the key and the secret when it’s actually a single object with key and secret attributes. That took some time to figure out.

To avoid repeating a big chunk of code eight times, I wrote a module, diary.py, with a function that can be called from all the other scripts:

python:
 1:  import dropbox
 2:  from datetime import datetime
 3:  
 4:  def add_entry(entry):
 5:    "Add a timestamped entry to today's diary file."
 6:  
 7:    # Initialize Dropbox.
 8:    app_key = 'aaaaaaaaaaaaaaa'
 9:    app_secret = 'bbbbbbbbbbbbbbb'
10:    access_key = 'ccccccccccccccc'
11:    access_secret = 'ddddddddddddddd'
12:    sess = dropbox.session.DropboxSession(app_key, app_secret, 'dropbox')
13:    sess.set_token(access_key, access_secret)
14:    client = dropbox.client.DropboxClient(sess)
15:  
16:    # Dates, times, and files.
17:    folder = '/Elements/Diary/'
18:    current = datetime.today()
19:    filename = current.strftime(folder +'%Y-%m-%d.txt')
20:    timestamp = current.strftime('%H:%M')
21:    dfiles = [ f['path'] for f in client.metadata(folder, list=True)['contents'] ]
22:  
23:    # Get the contents of today's diary file if it exists.
24:    if filename in dfiles:
25:      f = client.get_file(filename)
26:      log = f.read()
27:      f.close()
28:    else:
29:      log = ''
30:  
31:    # Add a new entry and save. Creates a new file if it doesn't exist.
32:    log += '%s\n%s\n\n' % (timestamp, entry)
33:    client.put_file(filename, log, overwrite=True)
34:  
35:  if __name__ == '__main__':
36:    add_entry('hello')

The function defined in this module, add_entry, does exactly what you’d expect from its name. Its single argument, entry, is what comes after the timestamp in a diary entry.

Lines 8–13 use the keys and secrets generated earlier to gain access to my Dropbox files. Line 14 initializes a Dropbox client process that handles the reading and writing of the files.

Lines 17–20 define the name and location of the diary file and define the timestamp. You’ll notice that my Diary folder is a subdirectory of a folder named “Elements.” Old-timers might remember that when the Elements app was the hot iOS text editor, it forced you to put all your files into a namesake Dropbox folder. I’ve linked every iOS text editor since then—none of which have been so restrictive—to that same folder.

Line 21 gets the names of all the files in the Diary folder. Line 24 then checks to see if there’s a file in there for today. If there is, it reads all the text from that file and puts it in a variable called log. If there’s no preexisting file for today, log is initialized to the empty string.

Line 31 adds the timestamp and entry to the end of log, and Line 32 writes log out to today’s file. This creates the file if it doesn’t already exist and overwrites the existing file if it does.

With diary.py doing all the hard work, the individual scripts for each common entry are easy. Here’s the one named Leave Home.py:

python:
1:  import diary
2:  import sound
3:  import webbrowser
4:  
5:  diary.add_entry('Leaving home')
6:  sound.play_effect('Coin_2')
7:  webbrowser.open('launch://')

Line 5 writes the entry, Line 6 plays a sound so I know when it’s done, and Line 7 takes me back to Launch Center Pro. The other seven scripts are exactly the same except for the argument to add_entry.

Which leaves just the definitions for the LCP actions. Here’s one:

Leave Home LCP action

The URL is

pythonista://Leave%20Home?action=run

I suppose I shouldn’t have left the space in the script name—that’s the reason for the %20. The .py extension isn’t needed in the URL because Pythonista knows to add it.

Apart from the quick, one-handed entry, the best thing about this solution is that it’ll be easy to extend if I start using other common entries in the future.


  1. I think Editorial would work, too, but I’m not as familiar with it. 

]]>
http://www.leancrew.com/all-this/2014/08/work-diary-revisited/feed/ 0
Back to LaunchBar http://www.leancrew.com/all-this/2014/08/back-to-launchbar/ http://www.leancrew.com/all-this/2014/08/back-to-launchbar/#comments Tue, 19 Aug 2014 01:50:50 +0000 http://www.leancrew.com/all-this/?p=2291 I gave Alfred a fair shot, I think. A two- to three-week trial in which I used it exclusively on both of my Macs. I even created some workflows to run scripts that I used to run through LaunchBar. And I really wanted Alfred to “stick,” because it uses far less memory than LaunchBar. But I’m back running LaunchBar again.

Two things brought me back. First, I didn’t like how Alfred wanted me to start folder and file searches by hitting either the spacebar or the single quote key. There are ways to have Alfred search files and folders without using this signal, but the preference pane for changing the setting warns against it. I didn’t want to slow Alfred down.

Alfred defaults

Which leads to my second problem: Alfred was, on my iMac at least, distinctly slower than LaunchBar at finding files and folders. I didn’t notice a speed difference on my MacBook Air—probably because its “disk” is all flash storage and only 128 GB—but Alfred’s lag was palpable on the iMac. It drove me crazy.

So what about LaunchBar’s huge appetite for RAM? That was, after all, the reason I gave Alfred a try. I went through LaunchBar’s index settings and pared down both the number and depth of the folders it indexes. I still get the quick results I want—I’m not sure why some of the settings were the way I used to have them—and LaunchBar’s long-term memory footprint is now down to about 100 MB on the MacBook Air and about 150 MB on the iMac. To be sure, this is about an order of magnitude more than what Alfred uses, but it’s a far cry from the 500–900 MB that LaunchBar was using before. And it’s worth it to get the behavior I want.

]]>
http://www.leancrew.com/all-this/2014/08/back-to-launchbar/feed/ 0
TextExpander and Numbers http://www.leancrew.com/all-this/2014/08/textexpander-and-numbers/ http://www.leancrew.com/all-this/2014/08/textexpander-and-numbers/#comments Fri, 15 Aug 2014 05:07:46 +0000 http://www.leancrew.com/all-this/?p=2290 When Apple revived the iWork apps after their four-year coma, users soon found that the newly awakened versions were diminished. Some of the features that were cut have been brought back, but the ability to define named constants in Numbers—which I used in my expense report template—has not reappeared. I’ve learned, though, that I can use TextExpander instead, and I now have a few simple snippets that are even easier to use than named constants.

I use the snippets to enter mileage expenses when I drive my car on business. The IRS rate changes from year to year—currently it’s 56¢ per mile—and I hate having to look it up. As I said, I used to have a constant, named miles, defined in my expense report template to equal the current rate. To enter the mileage expense for a 25-mile trip, for example, I’d type

=25*miles

into the cell and it would do the substitution and the calculation. Simple, but no longer possible. I suppose I could set up a cell in a hidden part of the expenses table and get the same effect, but I don’t like hidden cells. It’s too easy to make mistakes when you can’t see everything.

I set up an Expenses folder in TextExpander. The snippets within it expand after any character and work only in Numbers.

TextExpander Expenses folder

The fundamental snippet in the group is for the mileage rate. You might think I could just define it as 0.56, and that’s what I tried first, but I soon found that Numbers does some odd things with typed input. When I tested the snippet by typing

=25*;mi

into a cell, I heard the TextExpander expansion sound, and the ;mi disappeared, but nothing was substituted in its place. After a bit of tinkering, I found that a snippet with the content =0.56* would always expand, so that’s what I used.

Mileage rate snippet

Now I type ;mi into a cell, it expands to =0.56*, and I type the number of miles as the second term of the multiplication instead of the first. It’s a little different from my old habit, but it was easy to get used to.

Trips to the airport are pretty common, so I defined two other snippets, one for the trip to Midway and another for the trip to O’Hare. They start by invoking the mileage rate snippet and then add the number of miles to the end. If the mileage rate changes next year, I only have to change one snippet.

Midway snippet

I have a tendency to think in terms of complicated AppleScript or shell script snippets, but it’s often the simplest snippets that are the most useful.

In fact, as I was typing this up, I realized that snippets for the tolls I pay on my way to and from the airports would be just as valuable. I’ll be making those as soon as this is published.

]]>
http://www.leancrew.com/all-this/2014/08/textexpander-and-numbers/feed/ 0
A brief construction bestiary http://www.leancrew.com/all-this/2014/08/a-brief-construction-bestiary/ http://www.leancrew.com/all-this/2014/08/a-brief-construction-bestiary/#comments Tue, 12 Aug 2014 05:59:04 +0000 http://www.leancrew.com/all-this/?p=2289 This post was inspired first by Marco Arment and his son, Adam:

Fake Cheerios are better from a backhoe. @ Mont Olympos Restaurant instagram.com/p/rhVYe4w5Ii/
Marco Arment (@marcoarment) Aug 10 2014 9:18 AM

Click the Instagram link to see Adam using a clever spoon substitute. My predictable reaction:

@marcoarment I love the photos of your son and his toys but feel obligated to point out that that’s not a backhoe.
Dr. Drang (@drdrang) Aug 10 2014 11:51 AM

The post was further inspired by Daniel Jalkut, who, like all smart people, isn’t afraid to confess his ignorance on topics outside his comfort zone:

@marcoarment @drdrang Front end loader? Everything I know about trucks comes from those baby picture books.
Daniel Jalkut (@danielpunkass) Aug 10 2014 1:21 PM

What I know about construction equipment comes from growing up with a father who was a design engineer at Caterpillar for 30 years and from my own 20+ years investigating equipment failures. This, far more than the little amateur programming projects I usually write about here, is my comfort zone. So I decided to break out of my usual blogging habits and actually write about something I know.

This is also an exercise in nostalgia. The photo of Adam reminded me of my older son, Joe, who was thoroughly obsessed with construction equipment when he was that age. Nowadays, as a tall, deep-voiced high school senior, he wouldn’t know the difference between a loader and a backhoe, but when he was 3–4 years old, he was an absolute expert. The only thing he liked more that flipping through books with pictures of Big Muskie and the Silver Spade, was going with me to local construction sites and seeing machines at work.

The equipment names I’ll be giving here are what manufacturers use. Construction workers have any number of names for these machines—a small percentage of which don’t even involve profanity—and I’ll include as many of these nonstandard names as I can think of.

Bulldozer

Cat D6T

Photo from Caterpillar.

Dozers are the ur-machine of earthmoving, and the segmented steel tracks they run on are what gave Caterpillar its name.1 Each individual segment is called a shoe, and the spines that stick out of the shoe and dig into the soil for traction are called grousers. The tracks are meant to handle rough terrain while also spreading the load of the machine over a large area of ground contact.

The single wide blade at the front is for grubbing, pushing, and smoothing. Hydraulic cylinders behind the blade adjust its elevation, tilt, and horizontal angle. Dozers are often fitted with a ripper tooth on the back for loosening hard soil and are also used to pull other equipment around on a job site.

Loader

Cat 966M wheel loader

Photo from Caterpillar.

Lots of machines are called loaders, but the most common is the wheel loader, shown above. It’s not called a wheel loader because it loads wheels, it’s called that because it has wheels. It really should be called a wheeled loader, but it’s too late to change now.

Loaders have a wide bucket on the front that can be used for shallow digging but is usually used to scoop up loose material and load it2 into trucks. The position of the bucket has led to these often being called front-end loaders, but the front-end part is redundant. I’ve never seen one with a bucket at the back end.3

Some loaders run on tracks instead of wheels. As you might guess, they’re called track loaders. When Joe was at the peak of his machinery love, he was with me once at a store, looking out the front window at some construction work going on across the street. Another little guy, about a year older, was watching too, and said he liked the bulldozer. “That’s not a bulldozer,” said Joe. “That’s a track loader.” I was never prouder.

The very small loaders you see used by landscapers are officially known as skid steer loaders but are usually called Bobcats for the same reason facial tissues are usually called Kleenex.

Update 8/13/14
Reader Jonas Nilsson sent me a link to this image of a Volvo tractor with a loader attachment at its back end. According to Jonas, the name of this equipment in Swedish translates to back loader or back-end loader. You’ll note that in the linked photo the attachment is equipped with forks, not a bucket, but the mechanism could certainly accomodate a bucket.

Back loader attachment

Photo from Wikimedia.

Jonas says these back loaders used to be popular in northern Europe because they were cheap, but their disadvantages eventually outweighed the cost savings and they’re fairly rare now. I’ve seen plenty of farm tractors in the US with loader attachments on the front, but never anything like this. Thanks, Jonas!

Excavator

Cat 324E excavator

Photo from Caterpillar.

Excavators are for serious digging. They have a long, deep reach, and can switch buckets quickly for different types of digging operations. You’ll often see them outfitted with slings and cables to pick up pipe sections and lower them down into the trenches they just dug.

Many people refer to excavators as backhoes, but this isn’t quite right because the bucket is on the front of the machine, not the back. I’ve also heard them called trackhoes, which makes sense because they’re hoes on tracks,4 but very few people use that name and no manufacturer does.

By the way, there are two fundamentally different types of digging machines, and they get their names from the hand implements they mimic. Shovels dig by scooping down and away, hoes dig by drawing down and back. Hoes are more common, but you probably remember a famous shovel.

Mike Mulligan

Photo from Amazon.

Here’s a little more excavator nomenclature. The two parts of the arm are called the boom and the stick. The boom is the piece closest to the machine; the stick is the piece between the boom and the bucket. The boom, the stick, and the bucket are operated independently.

Backhoe loader

Cat 420F backhoe loader

Photo from Caterpillar.

The backhoe loader (often called the loader backhoe) is a hybrid machine with a loader bucket on the front and an excavator attachment on the back. For this machine, the word backhoe makes sense because the hoe is on the back. The operator, who normally faces forward toward the loader bucket, swings the seat around when it’s time to use the backhoe. The legs off the rear are called outriggers, and they’re brought down to stabilize the machine when digging with the backhoe.

On some machines, the backhoe is truly a separate attachment to a tractor. On this type of equipment, the backhoe has its own little seat.

Bradco backhoe

Photo from Gearmore.

Scraper

Cat 621K scraper

Photo from Caterpillar.

Scrapers are like dozers in that they have a blade that can cut through soil and level the ground. But a scraper doesn’t look anything like a dozer because its blade is at the bottom of a bowl—that’s the low part at the rear—which fills with the soil the blade cuts. A scraper can also be used “in reverse,” dumping soil out of the bowl and leveling it as it’s driven around the site.

I once had a project in Virginia in which the client kept referring to pans being used on his jobsite. It took me a while to realize he was talking about scrapers, substituting pan for bowl and then using that word for the entire machine. Even my dad hadn’t heard that one before.

Soil compactor

Cat 815F soil compactor

Photo from Caterpillar.

Soil compactors are often equipped with dozer blades to push soil around, but their shaped steel wheels are intended to do almost the exact opposite of a dozer’s tracks. The wheels focus the weight of the compactor onto a very small area to make the underlying soil more dense. The denser the soil, the better it is as a base for a roadway, parking lot, or floor slab.

I said brief

Because this is a blog post, and not a Dorling Kindersley book, I’m going to stop here, even though I haven’t even finished with earthmoving equipment. This makes for a good start, though, and should allow you to identify most of the machinery you see despoiling that nice wooded area to put in a strip mall.


  1. There are dozers with wheels, but they’re rare. Dozers are commonly used in areas that need to be smoothed out before wheeled vehicles can enter and work.

    Fun trivia: Caterpillar’s in-house newsletter was, and maybe still is, entitled Tracks and Treads

  2. Hence the name. 

  3. Now I have. See update below. 

  4. There are wheeled excavators, but they’re rare. 

]]>
http://www.leancrew.com/all-this/2014/08/a-brief-construction-bestiary/feed/ 0
Afghanistan, July 2014 http://www.leancrew.com/all-this/2014/08/afghanistan-july-2014/ http://www.leancrew.com/all-this/2014/08/afghanistan-july-2014/#comments Wed, 06 Aug 2014 00:28:11 +0000 http://www.leancrew.com/all-this/?p=2288 Afghanistan made the news today, mainly because Major General Harold Greene was killed in an “insider attack” at a training base for Afghan soldiers. General Greene isn’t in this graph, but he’ll appear in the next one, joining nearly 3500 others.

Afghanistan, July 2014

]]>
http://www.leancrew.com/all-this/2014/08/afghanistan-july-2014/feed/ 0
Modular URL shortening TextExpander snippets http://www.leancrew.com/all-this/2014/08/modular-url-shortening-textexpander-snippets/ http://www.leancrew.com/all-this/2014/08/modular-url-shortening-textexpander-snippets/#comments Tue, 05 Aug 2014 05:03:49 +0000 http://www.leancrew.com/all-this/?p=2287 Yesterday, John Flavin pointed out that my TextExpander snippets for getting Google-shortened URLs could be built better:

@drdrang Why repeat the ;furl code here? Why not just use %snippet:;furl% and make the whole thing a TE shell script?
John Flavin (@JFlavin) Aug 3 2014 11:11 AM

He’s right. Although I was thinking my snippets had to be self contained, they can call other snippets and incorporate the results—even if the snippet that’s doing the calling is a shell script or AppleScript snippet. TextExpander does the expansion first and then runs the script. So I refactored my snippets this way:

First, there’s my old snippet for getting the (unshortened) URL of the active browser tab, ;furl. It’s an AppleScript snippet with the following content:

applescript:
 1:  tell application "System Events"
 2:    set numSafari to count (every process whose name is "Safari")
 3:    set numChrome to count (every process whose name is "Google Chrome")
 4:  end tell
 5:  
 6:  if numSafari > 0 then
 7:    tell application "Safari" to get URL of front document
 8:  else
 9:    if numChrome > 0 then
10:      tell application "Google Chrome" to get URL of active tab of front window
11:    end if
12:  end if

(Note that I’m now using Vítor Galvão’s one-liner for Chrome.)

Next, I have a Python script, gshorten, that’s structured like the Pythonista script I use for shortening URLs on iOS, except that it takes the original URL from the command line and returns the shortened URL to standard output. It’s saved in my ~/Dropbox/bin folder. Here it is:

python:
 1:  #!/usr/bin/python
 2:  
 3:  import requests
 4:  import json
 5:  import sys
 6:  
 7:  # Build the request.
 8:  shortener = "https://www.googleapis.com/urlshortener/v1/url"
 9:  longURL = sys.argv[1]
10:  headers = {'content-type': 'application/json'}
11:  payload = {'longUrl': longURL}
12:  
13:  # Get the shortened URL and print it.
14:  r = requests.post(shortener, headers=headers, data=json.dumps(payload))
15:  sys.stdout.write(r.json()['id'])

The snippet I use to shorten the URL of the front browser tab uses both of these. It’s a shell script snippet with abbreviation ;surl and this content:

bash:
#!/bin/bash
~/Dropbox/bin/gshorten '%snippet:;furl%'

It runs the ;furl snippet and uses the result as the argument to gshorten. What’s nice about this solution is that it’s using AppleScript for what it’s good for (communicating with applications) and Python for what it’s good for (everything else).

Finally, the snippet I use to shorten a URL on the clipboard has the abbreviation ;scurl and this content:

bash:
#!/bin/bash
~/Dropbox/bin/gshorten '%clipboard'

It’s basically the same as ;surl except that it uses the clipboard as the argument to gshorten.

Splitting things up this way makes my system a bit more complicated, but there’s less repetition and, more important, each component does one thing. If I need to change the code for getting the front tab’s URL (to add another browser, for example, or if a browser changes its AppleScript library), I only have to change the code in ;furl. Similarly, if Google changes its API, I only have to fix the code in gshorten.

Someone my age should know enough to use modular design in the first place. Thanks to John for straightening me out.

]]>
http://www.leancrew.com/all-this/2014/08/modular-url-shortening-textexpander-snippets/feed/ 0