19?! Wow…

Today we remember Nina who would have been 19 today.

Today we remember Nina who would have been 19 today. Impossible for me to really imagine her at 19 since she didn’t live to 4, but here she is on her 2nd birthday in her new dress from a friend of grandma’s in Kenya:

Nina 2nd birthday in her new birthday dress made by grandma’s friend in Kenya

I woke up this morning remembering what an intense day this was 19 years ago and the intense week that followed. We knew she had hydrocephalus and that she’d need a shunt in her brain to relieve the CSF pressure, but we didn’t know she’d be in the neonatal intensive care unit (NICU) for a week and we definitely didn’t expect all the other medical challenges she was born with. Nor did we expect the three other major surgeries she’d need in that first year (spinal cord surgery, intestinal surgery, eye surgery).

It wasn’t until a couple of months before this picture on her 2nd birthday that we finally got a diagnosis of Fanconi Anemia (FA), and some idea of what to expect for her as a result. Up until then it was a mystery to her doctors. Unfortunately, that expectation was likely a short life due to the type of FA she had. She had a pretty great year from this birthday through the next one. And then a month not so great due to brain surgery to remove a new tumor, but then a really great summer of family visitors, and good early fall before her decline and departure.

Outcomes are much better now for people with FA, but it’s still tough for many. These improvements are largely thanks to the efforts of researchers supported by the Fanconi Anemia Research Fund (FARF) and all the family and friends who’ve raised money for them to fund research over the years (including ours). Much of this research has shed light on, and improved treatments for, cancer as well as FA due to physiological pathways in common between the two and the higher determinism for FA.

Anyway, it’s been a long road, but we feel very lucky to have had Nina in our lives for part of it. Hug the ones you love.

Build Racing circa 2006

Found an old document where I’d written down some data on build timing and though it might be fun to share it.

Did some build racing of a fairly large codebase for a widely used macOS application from a company I was working for. Thought it might be fun to see the progression.

I loved the Quad G5 I bought for myself (employer wasn’t spending that kind of money) as an upgrade from the dual G5 I first bought. What an amazing jump in speed with the Quad G5! The intel based Macs were a significant jump in performance though and cheaper and sucked a lot less electricity (turning on the Quad G5 would trip my UPS about 50% of the time – it had a nasty initial surge).

—-

This is an ant build of {REDACTED}. Interestingly, the second build is faster
even though we do a clean before each build.. suggests our “clean” isn’t
really cleaning everything…? Maybe source file and system library caching in the file cache? Anyway, clearly not very carefully done, but amusing all the same. You can see why I didn’t work on my 17″ G4 laptop much – ouch!

Mac Mini 1.66 GHz core duo, 2G of RAM

1st build: 26 min 58 sec
2nd build: 25 min 6 sec

same machine but put source on an external firewire 400 drive:
remove objects directory (like 1st build):

3rd build: 30 min 4 sec
4th build: 27 min 10 sec

17″ Powerbook G4, 1.33 GHz, 1G RAM

1st build: 57 min 50 sec
2nd build: 55 min 26 sec

Dual G5 2Ghz, 1.5G RAM: (I think this hard drive must be fragmented or
something)

1st build: 22 minutes+
2nd build:

“Quad” G5 2.5GHz, 2.5G RAM:

1st build: 9 min 4 sec
2nd build: 8 min 16 sec

**WINNER *** (and it cost $800 less than the Quad G5!)
NEW Mac Pro (guessing: Dual 2.66GHz dual-core Xeon with 1G of RAM):

1st build: 8 min 4 sec
2nd build: 7 min 9 sec (+/-)

Implanted Medical Devices, OSS, Open Hardware , Right to Repair, … and Electric vehicles.

Implanted medical devices from companies that go under or discontinue them have a major impact on the humans those devices have been implanted into. How do we mange this as a society in ways that doesn’t inhibit innovation and progress?

Imagine you’ve got a high-tech implant in your retina that gives you a crude but effective form of vision. Now imagine the company that produced the implant suddenly goes out of business, and will no longer service or fix your implant

Glenn Zorpette, on twitter

He’s referencing this article:

THEIR BIONIC EYES ARE NOW OBSOLETE AND UNSUPPORTED
Second Sight left users of its retinal implants in the dark

spectrum.ieee.org, (article)

I read this article last night and I’ve been thinking about it ever since. I don’t have an answer I’m convinced is complete yet, but it does seem like this situation represents a strong vote for FDA approval of medical implant requiring an implant meet the following standards:

  • Right to Repair requirements
  • Open Source Hardware
  • Open Source Software

But how do we do that in a way that doesn’t prevent companies making the massive R&D effort and incurring the corresponding expense to create these devices despite these requirements? Companies and investors will likely feel they’ll have insufficient time to earn back their investment, let alone the profit investors want, if their work can just be easily copied because it’s open source hardware/software.

I don’t have an answer, but the following come to mind as possibilities. I encourage you to add any practical ideas you have to the comments below.

  • Federal R&D grants for companies that are working on products that meet these guidelines (pre-launch funding).
  • R&D tax credits/incentives for companies that release products under this framework (pre- post-launch funding/incentives).
  • Have the technology held in an escrow system for hardware & software source that automatically becomes public 5 years (say) after shipping the approved device so companies have time to make their investment plus profit back.
  • Perhaps companies should be encouraged to patent what they create (discount the cost of that?) with a requirement that they also publish their hardware & software as open source restricted to non-commercial use only by others for as long as the company remain in business their patent is still in force (maybe limit patent duration to 10 years post product release or something)? They could still charge too much so as to make parts “available”, but not really available except to the super wealthy.
  • Maybe only non-profit entities can make implantable medical devices for approval and they will be required to follow the guidelines above. Investors don’t “invest” in these companies in a traditional sense, but perhaps they can ‘donate’ the loan of capital with a maximum interest return specified by statute (or something like that).

Curious what ideas others have.

Seems like something we need to solve – probably through legislation, but I’m open to other ideas. If done via legislation, we need that legislation crafted by people who actually understand the technological and business dynamics sufficiently well and who care about the people in whom these implants are placed sufficiently more than a desire for profit; we want good laws that actually work and don’t inhibit R&D and innovation so much we make no forward progress but also don’t risk leaving patients out in the cold, suddenly unable to see.

Postscript

I did also think about how this isn’t the first such device – I have at least two friends/colleagues with pacemakers that have been surgically implanted into their bodies. So this isn’t an entirely new thing.

I’ve also been thinking about this in the context of electric vehicles – how many of the new electric vehicles / companies are going to go out of business or decide it’s not worth it for them to keep maintaining or supporting early models that didn’t sell well?

Do all those vehicles prematurely become garbage because the battery controller software is closed source and so can’t be updated to work with new battery technology? Or because the inverter goes bad and the specifications for it aren’t available any more and so no one can create an aftermarket replacement? Or vehicles that had too few for it to make financial sense for a third market parts manufacturer to bother? (See man blows up Tesla Model S because replacement battery is too expensive to justify).

I don’t think we can afford to be making so much garbage. There’s a lot of embodied energy in an EV and a massive level of promotion for people to switch to EVs from internal combustion engine (ICE) vehicles. Those ICE vehicles can be kept running for 20, 30, 40, even 50 years if they were popular when they were released and so third party parts manufacturers have figured out how to make parts for them.

Batteries in electric vehicles aren’t going to last even half the lower end of that spectrum.

This seems like an issue that needs to be addressed. Not as individually impactful as having your medical implant “End of Life’d”, but still.

Automatic Once-a-Day Time Machine Backups

Update: So in macOS 12 (and likely v11 and maybe v10) you have to give cron Full Disk Access for it to work. This seems less than ideal from a security perspective, so I’ve move to using launchd via a LaunchAgent plist file. Documentation on how to use cron is in an addendum in case you prefer that.


My wife is using an older MacBook Air from late 20101 and it can’t handle a Google Meet meeting, Chrome with a bunch of tabs open, and a Time Machine backup (all over WiFi) without the video meeting having trouble. We still wanted to back it up to the two TimeCapsules we have though.

I tried just having her run a backup manually when she was done for the day, but she’s tired then and so backups weren’t happening regularly at all. Thus, it was clear I needed a way to automate this. Turns out it’s not that difficult. This post explains how.

Quick summary

  • Setup Time Machine backup destinations
  • Run a first backup to each backup destination
  • Option 1 (described in an addendum since launchd is preferred by Apple):
    • Use crontab to setup a daily call to tmutil startbackup --auto --rotation
    • Use System Preferences > Security & Privacy > Full Disk Access to give /usr/sbin/cron full disk access
  • Option 2:
    • Create a LaunchAgent plist to invoke tmutil startbackup --auto --rotation at the desired time.
    • use sudo launchctl bootstrap gui/501/ /Users/{your-username}/Library/LaunchAgents/{your-launch-agent-plist-filename} to get the system to load and enable your
  • Use Energy Saver / Battery settings, or pmset repeat wake with appropriate time and days to wake up the computer a couple of minutes before that crontab command trigger time.

Step by Step instructions

  1. First step – create the Time Machine backup destinations in the Time Machine settings inside System Preferences.
  1. Run the first backup to each destination – either manually (via right-click on the destination drive icon in System Preferences > Time Machine view), or automatically by enabling “Back Up Automatically” in Time Machine settings and then waiting until they’ve both completed their first backup (don’t forget to turn off automatic once the first backup to each has run!).
  1. Decide what time you want your daily backup to run. I chose 12:59AM.
  1. Now create a LaunchAgent file for your task. The easiest way is to use LingonX, but you can create the file in a text editor like the excellent BBEdit and may want to refer to this very helpful documentation for launchd.

Name your file something that makes sense to you, I matched the file name to the label, so: “com.geekanddad.DailyTimeMachineBackup.plist” is what I used.

Contents should be something like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.geekanddad.DailyTimeMachineBackup</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/tmutil</string>
    <string>startbackup</string>
    <string>--auto</string>
    <string>--rotation</string>
  </array>
  <key>StartCalendarInterval</key>
  <array>
    <dict>
      <key>Hour</key>
      <integer>00</integer>
      <key>Minute</key>
      <integer>59</integer>
    </dict>
  </array>
</dict>
</plist>
  1. If doing this manually with a text editor, you’ll need to save this file into ~/Library/LaunchAgents/ and then you’ll need to tell launchd about it via something like:

    launchctl bootstrap gui/501/ /Users/dad/Library/LaunchAgents/com.geekanddad.DailyTimeMachineBackup.plist

    Note 1: If you don’t know what your uid (User ID) is (it’s the number after “gui” in the service domain target argument above), you can use launchctl manageruid command to find out.
    Note 2: If this doesn’t work, try running it via sudo and you’ll get more verbose error messages.
  1. Now all you need to do is make sure your Mac is awake at 12:59am 🙂

    A note about the time: Since waking up triggers connecting to the network which triggers auto-fetching of mail, likely calendar syncing, and who knows what other Apple stuff and this was an old and slow Mac, I chose to wake it up at 12:57am so it would have 2 minutes to complete all of the network stuff before the Time Machine backup tried to start. This is because if it’s too slow sometimes Time Machine on this old version of macOS will decide that “the backup destination isn’t available” and it will fail.

    I think you can do this via the Energy Saver (“Battery” in macOS 12.x) System Preferences pane under “Schedule” (for macOS 12.x) by selecting the “Startup or wake” checkbox and picking “Every Day” and the time you chose above.

    I didn’t go this route because I didn’t want it to wake up a shutdown Mac which might not be plugged in and then my wife would wake up to a dead laptop (not good for my reputation! :)).

    However, if that would work for you, I recommend trying that out because it’s easier.

    What I did:

    sudo pmset repeat wake MTWRFSU 00:57:00

Which sets a repeating wake event for 12:57am every day of the week. You’ll note that I didn’t use wakeorpoweron here because I only want it to wake up a sleeping computer and do not want it to turn on a shutdown computer.

That’s it!

All she has to do now is leave her laptop open at night when she wants it backed up (it won’t wake up if the lid is shut and no external monitor is attached).


Addendum – using (crontab):
  1. Using Terminal, initiate editing of the crontab for the current user (which is what I did), or potentially a system crontab (I didn’t look into this):

crontab -e

This puts you into your terminal editor with the current user’s crontab file open. Once there, add the following two lines

# For daily backups
59 0 * * * /usr/bin/tmutil startbackup --auto --rotation

This crontab entry says to run the tmutil command at 59 minutes after midnight every day. The parameters to tmutil are telling it to start a backup, run it as if it was a system initiated backup, and to automatically rotate between multiple backup destinations (you only need the last parameter if you have multiple defined).

  1. Give cron permissions necessary to run
    1. Open “System Preferences…” from the Apple menu and select the “Security & Privacy” icon.
    2. Then select the “Privacy” tab and scroll through the list on the left and select “Full Disk Access.”
    3. Select the lock icon in the lower left and enter an administrator’s credentials.
    4. select the + icon below the list of applications
    5. type Cmd+shift+g to display the path entry file selection interface and type: /usr/sbin/cron and select the cron binary

The window should look like this when you’ve got it added properly:

Security & Privacy panel inside System Preferences with the Privacy tab selected and Full Disk Access selected from the list on the left.  Shows the cron command line tool in the list on the right with the enabled checkbox to the left of the tool name checked.


Footnotes

1) She’s since upgraded to a late 2020 MacBook Air and is loving it, as you’d imagine :). Retina screen, insanely faster, insanely long battery life, etc. Only thing she’s annoyed by is all the dongles required to connect to her external keyboard, mouse, and external display 🙂 (back)

Life planning circa early 2001

Old life-planning image that Jaimee Jaimee’s Coffee With Jaimee – getting unstuck radio show made me think of.

Just started listening to the first couple of episodes of Jaimee Finney’s new live radio show Coffee With Jaimee – A Show About Getting Unstuck and have been enjoying it quite a bit.

In these first two episodes Jaimee talked about writing down what’s most important to you in your life in episode one, and then talked about writing down your big bulky desires or goals in episode two. This reminded me of something along these lines I did in early 2001 (?). Sharing it not because the content is particularly interesting, but to illustrate that “write down” doesn’t necessarily mean making a list in the usual way. My thought was that perhaps this might help someone feel free to diagram these things out in a way that organizes them by modality, or topic, or location, or whatever works best for them and to remind people that it doesn’t have to be a linear list.

Circle in the center containing core goals/values (Be a good dad; be a good mate; be healthy) and with "rays" of text coming out for various projects (software products, technologies to learn, house projects, and so on) and things to learn and do.

I redid this later and it got a bit more concentric circle oriented, but the shape is just whatever way helps you evaluate the relative importance of things to you, your life, those you care about, and so on, so I’d recommend not letting yourself be constrained by what I or anyone else has done.

(slight redaction to remove names of products and people as appropriate)

AppleScript to eject mounted local volumes

AppleScript to eject mounted attached volumes/disks.

I have a MBP which I use with a Thunderbolt dock to connect to various USB and thunderbolt hard drives, SSDs, and optical drives. This script lets me eject and unmount anything physically connected before disconnecting my Thunderbolt dock.

Yah, sure, OWC makes a utility you can install that’ll do this, but it installs a kernel extension which I wasn’t keen on installing.

-- AppleScript I wrote to eject mounted USB disks before I disconnect my USB-C hub.
-- Notes: 
-- this will halt a time machine backup to a locally mounted 
--   drive when it tries to eject it.
--   will also halt a time machine backup to a network destination.
-- tested in macOS 11.6 (2021.11.19)
-- License:  MIT

tell application "System Events"
  set ds to get disks
  
  -- for debugging
  if false then
    log "list of disks: "
    repeat with d in ds
      log (get the URL of d)
      log (get the name of d)
    end repeat
  end if
  
  log ("Ejecting local ejectable volumes")
  repeat with d in ds
    -- before we try to do anything with this disk    
    -- try to access the disk and catch any errors 
    -- as a way to test if the disk is still present.
    -- set a flag that we can test below.
    set diskAvailable to true
    try
      set trashme to (get the name of d)
    on error errormsg number errorno
      if errorno is -1728 then set diskAvailable to false
    end try
    
    -- Notes:
    -- ejectable excludes sparse volume mounts for time 
    -- machine, but also means other ejectables aren't unmounted…
    -- ...decided to remove this in the if clause below and let it halt 
    -- time machine backups even for network volumes also
    -- since I'm generally calling this script when I'm disconnecting
    -- the laptop and heading out.
    --         d is not ejectable and ¬
    
    -- starts with "Data@" excludes time machine local snapshot
    --    mounts during backups
    -- starts with file:///Volumes excludes file:///System/Volumes/... 
    --  system volumes.
    -- local volume excludes network mounts
    
    
    if diskAvailable and ¬
      d is local volume and ¬
      the URL of d starts with "file:///Volumes/" and ¬
      the displayed name of d does not start with "Data@" then
      log ("........ ejecting:  " & (get the name of d))
      tell application "Finder" to eject (get the name of d)
    else if diskAvailable then
      log ("   Skipping: " & (the URL of d))
    else
      log ("  Skipping disk that is no longer available")
    end if
  end repeat
  log (" all ejectable local volumes ejected")
end tell

Posted as a gist here for easier copying and using.

Faster to write a script than to deal with so many browser windows? Well, certainly more fun :)

AppleScript to move Safari windows up as much as the window closest to the top of the screen will allow.

There’s a bug in Safari 15.0 where it sometimes re-positions open windows when waking from sleep by moving all the windows down an amount such that the bottom of the lowest one is at the bottom of the monitor (or something like that? They all move down a lot).

If happen to place your Safari windows up enough so that another app’s window can be visible on-screen under them (chat in my case), and you have a few too many windows open in Safari (ahem!), then you might be very annoyed to have to over a hundred windows all back up again.

Now, you could go through your heap of open Safari windows, but if you’re a programmer than you might (likely incorrectly ;)) think it’d be faster to write an AppleScript to move them all back up again. Not that I’d do such a thing, you understand, but, purely for educational purposes, here’s the kind of script one might write (or the second version if the first one took 6 minutes process the > 100 Safari windows you had open) :). This one moves all Safari windows up the same amount to keep their relative positioning and moves them up as much as possible while still keeping the window positioned highest on the screen below the menu bar.

Disclaimer: I write zero to two AppleScripts a year and never really learned AppleScript. There’s almost certainly better ways to do this. But it works for me and fixes my windows after Safari munges them again. So GoodEnough™ 🙂

-- Put in the public domain with zero warranty of any kind
--
-- only tested on macOS 11.6, with Safari 13.0; ymmv

use scripting additions

tell application "Safari"
  set windlist to windows
  
  log "Examining " & length of windlist & " windows..."
  
  set lowestYWindow to first item of windlist
  set lowestYValue to get second item of (get bounds of lowestYWindow)
  
  repeat with wind in windlist
    set curValue to second item of (get bounds of wind)
    if curValue < lowestYValue then
      copy wind to lowestYWindow
      set lowestYValue to curValue
    end if
  end repeat
  
  -- subtract out the title bar height (hard coded - bad dog!)
  set yOffset to lowestYValue - 25
  
  if yOffset > 0 then
    log "moving " & length of windlist & " windows up " & yOffset & " pixels"
    repeat with aWind in windlist
      set aBounds to (get the bounds of aWind)
      set the second item of aBounds to ((get the second item of aBounds as integer) - yOffset)
      set the fourth item of aBounds to ((get the fourth item of aBounds as integer) - yOffset)
      set the bounds of aWind to aBounds
    end repeat
  else
    display alert ("The highest window already at the top!  Not moving any windows!")
  end if
  log "done"
end tell

Here it is in a gist for easier copy/edit, etc.

Blast from the past: “Bedtime conversations tend to be a little goofy when Dad’s doing lights out….”

Cleaning up an old family website (pre blog) for sharing stories with out-of-town family and found this bit of goofy-dad nonsense that made me laugh so I thought I’d share it:

—-

Bedtime conversations tend to be a little goofy when dad’s doing lights out….

A discussion of wavelengths of energy and radio astronomy leads to the following: 

Geek: How do you see things with xrays and radio waves?

Dad: Well you could look at the signals bouncing back. Where there is nothing you get no bounce-back, and where there’s a planets or moon or something you get a bounce back. How long it takes to bounce back tells you how far away it is. Longer wave lenghts show less detail than shorter wave lengths (long discussion of why).

One time there were these astronomers trying to discover new planets and they decided to create a gamma-wave telescope.

Geek: Did they find any?

Dad: Well, they thought they had, but things were kind of strange…. 

So then they sent gamma rays towards this one spot and they got ultraviolet waves back!

“That’s funny” the astronomers said to each other, “let’s try xrays.”

So they shot some xrays towards the same location… this time they got back radio waves! 

Geek: “They did?!”

Dad: “Yep!”

After trying to understand what kind of astronomical body could turn their xrays into radio waves of the frequency and waveforms they’d received back, someone got the idea to play the radio waves through a speaker. Boy were they surprised to hear “HEY! No Peeking!” coming out of the speaker!

(Geek breaks out in laughing!) 

“WHAT!??? said the astronomers. 

They sent back a radio signal on the same frequency saying, “Sorry, we didn’t know anyone was there!” 

They got a message back saying, “You didn’t? Didn’t you see my sign?”.

“What sign?” the astronomers sent back. 

“Check the ultraviolet signal we returned when you sent all those gamma rays,” was the reply. 

So the astronomers took the ultraviolet signal they’d gotten back and figured out it was a sign saying “Bob’s Spaceship Repair Shop.”

—-

The next several nights we’d hear “HEY! No Peeking!” coming from Geek’s room followed by lots of laughter so I guess it was a lasting laughable ™. 🙂

Aug. 2004. (Geek was 8)

Two books that changed my relationship with money

Two books that changed my relationship with money for the better:


 The Millionaire Next Door by Thomas J. Stanley and William D. Danko.

An older book, but the mental model of the people profiled is useful to understand and consider adopting elements of.

Your Money or Your Life by Vicki Robin & Joe Dominguez

I wouldn’t, and haven’t, gone full frugal as outlined in this book, but it’s useful to understand how far that axis of existence goes and then adopt the elements of it that work for you (we have adopted a lot of useful stuff from this book).

The links above are to Amazon (sorry) where you can get paper or Kindle versions, and here are Audible versions of both of these in case audio books work better for you:

The Millionaire Next Door

Your Money or Your Life

NOTE: Of course, both of these books would say “there is no reason to BUY these books! Get them from your library, or via inter-library loan if your library doesn’t have them.  If truly not available that way, buy them used.”   🙂

Regular Expressions for unicode string matching in Swift are pretty cool!

I had to do some validation on a username while coding an iOS app today and so dove into regular expression matching. The specification said “Usernames can include upper and lower case letters, numbers, periods, and underscores” and I’m figuring they’re thinking ASCII only. RegEx of [a-zA-Z0-9_.]+ kind of thing. Thinking of my twitter friend @krzyżanowskim and his posts about not being able to include the proper ż in so many places, I wanted to do better.

So I dove into the world of unicode regular expressions and found this very useful resource. I think I’ve figured out what might be a decent answer (please let me know here or on Twitter @GeekAndDad if you have advice to offer :)).

To include all letters, accented letters, symbols, numbers, an underscore or period (.), but exclude all other punctuation or spaces, I came up with this bit of Swift code:

func validateUsername( username: String) -> Bool { 
  // length tests go here and return false on failure 

  let expr = #"^[\p{L}\p{M}\p{N}_.\p{Me}\p{S}]+$"#
  let matchesRange = username.range(of: expr, options: .regularExpression)
  if matchesRange == nil {
    return false
  }

  // additional validation step here

  return true
}

Note that I don’t have to check matchesRange‘s lowerBound and upperBound against the string’s startIndex or endIndex because I’ve included the ^ and $ to indicate that everything in the string must match the expression.

Seems to work so far. I’m impressed and grateful that Swift’s regular expressions support these unicode specifiers (!!!).