Monday, January 30, 2023

Map Skills in the Hood

Last year, I realized I could brush up my map and compass skills by printing out a local topo map and using it to explore my neighborhood. I recently gave this a try and was richly rewarded.

Here was the first stop on my little adventure. One of the side streets near our home dead ends at a fence. It's hard to see, but on the other side of that fence is the Army Navy Golf Course with the clubhouse in the distance. I wondered if I could plot the location of this building on my map using my current location and terrain clues.

I grabbed my current location from the UTM/MGRS widget on my Garmin vĂ­voactive 4 watch.* Alternatively, I could have used the GPS Test app to learn my UTM coordinates from my phone.

I plotted these coordinates using the map's grid lines and a Map Tools Mini Corner Ruler. I noted the location as 'C'.

A quick glance at the compass told me that the clubhouse was due South from my position. Looking at the contour lines, I plotted point '1' in purple as my guess of the building's location.

Once at home, I used Google Maps to determine the latitude and longitude of the clubhouse. I plugged these values into Backcountry Navigator to reveal the equivalent UTM values. Finally, I recorded these coordinates in purple on my map by again using the Mini Corner Ruler.

Success! As you can see below, my guess of the building's location agrees with the actual value. I repeated this process a handful of times: plotting known values in black, guesses in purple and actual values in red.

Most of my guesses were fairly accurate. I ran into issues with guess '2' because I incorrectly converted miles to kilometers. Curse you imperial units!

*Alas, I didn't grab a photo of the actual coordinates at the fence-line. The coordinates in the picture are from another part of my stroll, but the concept is still the same.

Friday, January 27, 2023

The Goldilocks Problem, Backup Phone Edition

I've shared why I carry a backup phone, and the plan I use to power it. Now comes the fun part: talking about the device itself.

Here are three examples of what I consider top notch backup phones, but as you'll see one is clearly the winner. All three phones make use of the same old-school operating system which will be familiar to those of us who grew up on turn of the century Ericssons and Nokias. For everyone else, these phones will feel primitive. Remember: what they lack in pizzazz they more than make up for in functionality.

Finally, all three phones rely on 2G networks. One day, T-mobile & US Mobile may stop supporting this type of network. When that happens, these phones will be useless and I'll need to search out new devices. But until then, these devices rock. One just happens to rock more than the others.

The Slide: Too Little

The CR1102GD Slide, aka the M5 mini phone, is a remarkable device. It's easily one of the best phones I've ever owned. Weighing in at just over an ounce (31g!), having form factor of a credit card and costing $19.95, it's the just about the perfect minimalist communication tool.

The Slide has you covered for calls and text messages and includes extras like speakerphone, Bluetooth and a physical off switch to avoid power drain while not in use. If you pair it with a Micro USB to 3.5mm audio jack cable, you also get access to FM radio. You can even pair the device with your main cellphone, letting the Slide serve as a 'Bluetooth dialer.' This lets you handle this unassuming phone in public, while calls are routed through the $1,000 cell phone in you pocket.

The Slide isn't without its quirks. It doesn't pickup the current date & time from the cell network, so you have to set it yourself. And the screen and keyboard are obviously sub par. But still, as backup devices go, it's gold.

But, we can do better!

The A10: Too Much

The full metal construction and comparatively expansive color screen of the A10 1.77 HD mini phone makes it feel luxurious compared the Slide. The built in 3.5mm audio jack and support for capturing voice memos is a nice bonus, making it useful for on the go journaling.

Alas, the all metal construction is also the phone's Achilles' heel. The phone weighs in at a massive 66g (for context: my S22 Ultra, with case, weighs 300g), which I can't justify when there are lighter options out there. Like the Slide, it doesn't appear to pick up the date from the network either. Finally, for the life of me, I couldn't figure out how to get the battery removed to install an SD card.

Again, we can do better!

The Soyes 7S+: Just Right

The Soyes S7+, aka the PUSOKEI Mini Cell Phone, is a delightful step up from the Slide without the weight penalty of the A10. Weighing in at 36g, and being slightly thicker, yet narrower than the Slide, it maintains a tiny footprint. The phone adds a larger and more functional screen than the Slide, a very low resolution camera, flashlight and primitive Micro SD card support. And hallelujah, it gets its date and time from the network, so you don't need to set it manually.

The flat keyboard is handy for storage, but not as pleasant to use as the A10. The voice recorder of the A10 is probably more practical than the camera from S7+, but that hardly justifies the weight increase.

Overall, the Soeys S7+ is the way to go if you're looking for a backup phone that disappears in a murse, yet can be a lifesaver when you need it.

Thursday, January 26, 2023

Phone Plan Perfection: Picking a Backup Phone Service Provider

I like carrying a backup phone. While the phone handset gets all the glory, I realized that without a cell plan my little backup phone would be a lot less useful.

I've found US Mobile elegantly answers the question of which cell provider should I use. What makes them unique is their custom plans can be scaled way down to match my backup phone usage.

I currently pay US Mobile $2.00 a month for 75 minutes of talking, $1.50 a month for 50 text messages and $0.00 a month for data I don't use. Of course there are fees--there's always fees--but they are relatively minimal. For about $5.00 a month I can turn any random phone into a invaluable communication device.

Another wrinkle is that my backup phone requires a 2G network. US Mobile uses T-mobile as a network provider. While T-mobile has shut down their 3G networks, 2G continues to live on. This means that the quirky device I use as a backup phone (more on that soon), work seamlessly with US Mobile SIM cards.

I don't usually find myself heaping praise on cell phone companies, but US Mobile nails it this time around.

Wednesday, January 25, 2023

5 Reasons I Carry a Backup Phone

Here's my top five reasons I carry an itty bitty backup cell phone:

1. To find my 'main' phone. In that moment of panic when I realize my regular phone isn't in my pocket, I can use my backup phone to find out where it's located.

2. To let me communicate when my main phone gets lost, broken or separated from me. We ran into this over the summer when I handed my phone to my nephew to take pics. Shira and a few kids got separated from me and the rest of the little ones. Of course my nephew was in Shira's crew, safely holding my phone. My backup phone let us gracefully reconnect.

3. To access FM radio in an emergency. In a disaster, the humble FM radio can become a critical lifeline. That's why a radio is mentioned on Arlington County's build an emergency kit page as a 'basic emergency' item. Having the radio as part of my backup phone, rather than built into my primary phone, means that I can get info in a disaster while not running down the battery of my main device.

4. To avoid the distractions of a cell phone while still maintaining a safety net. I carry my backup phone on Shabbat, a day when I relish and recharge by being offline. By carrying my backup phone, I know I can still reach 911 or Shira in an emergency. The backup phone also disappears into a small zippered pocket on my running shorts; so it's ideal for taking on run when I'd like to go ultralight and leave my clunky phone behind.

5. To serve as a 2-Factor Authentication backup device. For critical accounts, like Google or Apple, I like being able to provide my backup phone's cell number as a yet another way to get a one time code delivered to me.

And here's 10 bonus reasons:

  1. To Test out SMS based Tasker routines.
  2. To avoid carrying a flashy phone in a high crime area.
  3. To avoid being a target for hackers.
  4. To experiment with low resolution photography.
  5. To hand to stranger so they can make a call.
  6. To share with someone so we can be temporarily in contact.
  7. To sneakily store names, numbers of other details in the phone's contact section.
  8. To access data stored on an SIM or SD card.
  9. For use as a four function calculator.
  10. To show kids what phones used to be like back in the day.

Tuesday, January 24, 2023

Review: A Woman of No Importance

One sign that I've been completely sucked into a story is when the plot starts to influence my IRL mood. This is where I found myself while listening to A Woman of No Importance: The Untold Story of the American Spy Who Helped Win World War II.

A double agent had infiltrate Virginia Hall's spy ring and now the authorities knew her identity and likeness. They were closing in and capture, torture and death were imminent. I was not pleased about this turn of events one bit and had a grumpy and sour mood to match. The fact that these events took place nearly 80 years ago as part of WWII was cold comfort.

These feelings are evidence of just how good the writing of A Woman of No Importance is, and how amazing Hall's life and accomplishments are.

My simplistic understanding of World War II is as American-centric as one would expect. To me, WWII is punctuated by Pearl Harbor, D-Day, the horrors of the Nazi Concentration Camps, and Hiroshima and Nagasaki. Hall's story greatly expanded this view by showing me the perspective of the war through a French person's eyes. From the toppling of France by Germany, to planting the seeds of a fragile resistance to--spoiler alert--an ultimate victory by the resistance and allied troops. Hall not just witnessed it all, but helped make it happen. This would be an impressive feat for anyone, but is even more remarkable when you consider her gender and status as an amputee would normally be an absolute deal-breakers for serving in an active war zone.

Hall's story is exactly why diversity is a feature to be nurtured, and not a bug to be endured. She demonstrated this not only by taking what appeared to be shortcomings, her gender and disability, and using them as strengths. But just as importantly, by showing that these were not her defining characteristics. Her street smarts, generosity of spirit, ability to be a quick study, thirst for making a difference and a boundless degree of fearlessness, all made her an ideal operator in the hazard filled world of spying and resistance building.

One difficult but poignant aspect of Virginia's story is how she keeps needing to prove herself over and over again. Her quality work for the State Department is consistently overlooked in favor of assuming her gender or disability should define and limit her. Perhaps the ultimate irony was when her request for promotion was brought to none other than FDR himself, a fellow citizen who had to overcome disability on a daily basis, and even he couldn't see her petition as worthy.

Perhaps that what makes Hall's story so compelling. She had to not only outwit and overcome the Vichy Police and Gestapo; she had to outwit and overcome her own employers and societal-expectations just to get into the fight. We should learn Virginia's story not just because she's a courageous and selfless role model, but because there are other 'Virginia Halls' out there that will thrive if just given the opportunity.

Wednesday, January 18, 2023

USGS Topo Maps from the Command Line

Below is a script that combines the USGS Product API and Google's Geolocation API to make a shell script to retrieve topo maps from the command line. 'Product' in this context refers to mapping products that the USGS makes freely available to the world.

This is a relatively easy script to write because the USGS API finds products given lat / long bounding box. Google Geolocation API will happily give you back just such a bounding box. This means you can seamlessly convert a place names into a searchable geographic location.

Here's the script in action. As you can see the USGS mapping products are treasure trove just waiting to be mined.


# Topo containing the White House

$ usgsassist -a topos -l "1600 Pennsylvania Ave, Washington DC" Washington West, DC,MD,VA 2019|2019-11-22|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/DC/DC_Washington_West_20191122_TM_geo.pdf

# Topo maps for Chicago

$ usgsassist -a topos -l "Chicago, IL" Arlington Heights, IL 2021|2021-04-16|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Arlington_Heights_20210416_TM_geo.pdf Berwyn, IL 2021|2021-04-23|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Berwyn_20210423_TM_geo.pdf Blue Island, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Blue_Island_20210420_TM_geo.pdf Chicago Loop OE E, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Chicago_Loop_OE_E_20210420_TM_geo.pdf Chicago Loop, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Chicago_Loop_20210420_TM_geo.pdf Elmhurst, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Elmhurst_20210420_TM_geo.pdf Englewood, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Englewood_20210420_TM_geo.pdf Evanston, IL 2021|2021-04-16|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Evanston_20210416_TM_geo.pdf Hinsdale, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Hinsdale_20210420_TM_geo.pdf Jackson Park, IL,IN 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Jackson_Park_20210420_TM_geo.pdf Lake Calumet, IL,IN 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Lake_Calumet_20210420_TM_geo.pdf Palos Park, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Palos_Park_20210420_TM_geo.pdf Park Ridge, IL 2021|2021-04-16|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Park_Ridge_20210416_TM_geo.pdf River Forest, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_River_Forest_20210420_TM_geo.pdf Sag Bridge, IL 2021|2021-04-20|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/IL/IL_Sag_Bridge_20210420_TM_geo.pdf

# Topo maps for all of Virginia

# Peek at the start of list. $ usgsassist -a topos -l "Virginia, USA" | head -5 Abilene, VA|2022-09-14|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/VA/VA_Abilene_20220914_TM_geo.pdf Abingdon, VA|2022-09-16|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/VA/VA_Abingdon_20220916_TM_geo.pdf Accomac, VA|2022-08-31|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/VA/VA_Accomac_20220831_TM_geo.pdf Achilles, VA|2022-09-09|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/VA/VA_Achilles_20220909_TM_geo.pdf Adams Grove, VA|2022-09-14|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/VA/VA_Adams_Grove_20220914_TM_geo.pdf # Peek at the end $ usgsassist -a topos -l "Virginia, USA" | tail -5 Woodsboro, MD 2019|2019-11-22|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/MD/MD_Woodsboro_20191122_TM_geo.pdf Wye Mills, MD 2019|2019-12-02|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/MD/MD_Wye_Mills_20191202_TM_geo.pdf Wyoming, DE 2019|2019-11-21|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/DE/DE_Wyoming_20191121_TM_geo.pdf Yellow Spring, WV 2019|2019-12-12|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/WV/WV_Yellow_Spring_20191212_TM_geo.pdf Zaleski, OH 2019|2019-12-03|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/OH/OH_Zaleski_20191203_TM_geo.pdf # the total number of maps $ usgsassist -a topos -l "Virginia, USA" | wc -l 1697

# Topo maps for a National Park

$ usgsassist -a topos -l "Rocky Mountain National Park, Colorado" Allenspark, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Allenspark_20220325_TM_geo.pdf Bowen Mountain, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Bowen_Mountain_20220325_TM_geo.pdf Chambers Lake, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Chambers_Lake_20220325_TM_geo.pdf Clark Peak, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Clark_Peak_20220325_TM_geo.pdf Comanche Peak, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Comanche_Peak_20220325_TM_geo.pdf Crystal Mountain, CO|2022-03-15|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Crystal_Mountain_20220315_TM_geo.pdf Estes Park, CO|2022-03-15|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Estes_Park_20220315_TM_geo.pdf Fall River Pass, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Fall_River_Pass_20220325_TM_geo.pdf Glen Haven, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Glen_Haven_20220325_TM_geo.pdf Grand Lake, CO|2022-03-16|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Grand_Lake_20220316_TM_geo.pdf Isolation Peak, CO|2022-03-15|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Isolation_Peak_20220315_TM_geo.pdf Longs Peak, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Longs_Peak_20220325_TM_geo.pdf McHenrys Peak, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_McHenrys_Peak_20220325_TM_geo.pdf Mount Richthofen, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Mount_Richthofen_20220325_TM_geo.pdf Panorama Peak, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Panorama_Peak_20220325_TM_geo.pdf Pingree Park, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Pingree_Park_20220325_TM_geo.pdf Raymond, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Raymond_20220325_TM_geo.pdf Shadow Mountain, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Shadow_Mountain_20220325_TM_geo.pdf Trail Mountain, CO|2022-03-25|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Trail_Mountain_20220325_TM_geo.pdf Trail Ridge, CO|2022-03-15|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/USTopo/PDF/CO/CO_Trail_Ridge_20220315_TM_geo.pdf

# Historic maps of Boston published from 1910-39

$ usgsassist -a historic -l "Boston, MA" | grep '|19[123][0-9]' USGS 1:24000-scale Quadrangle for Blue Hills, MA 1936|1936-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/24000/MA_Blue%20Hills_350022_1936_24000_geo.pdf USGS 1:24000-scale Quadrangle for Cohasset, MA 1936|1936-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/24000/MA_Cohasset_350067_1936_24000_geo.pdf USGS 1:24000-scale Quadrangle for Nantasket, MA 1936|1936-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/24000/MA_Nantasket_350329_1936_24000_geo.pdf USGS 1:24000-scale Quadrangle for Norwood, MA 1936|1936-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/24000/MA_Norwood_350406_1936_24000_geo.pdf USGS 1:24000-scale Quadrangle for Scituate, MA 1935|1935-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/24000/MA_Scituate_350536_1935_24000_geo.pdf USGS 1:24000-scale Quadrangle for Weymouth, MA 1936|1936-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/24000/MA_Weymouth_350724_1936_24000_geo.pdf USGS 1:62500-scale Quadrangle for Abington, MA 1920|1920-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/62500/MA_Abington_352433_1920_62500_geo.pdf USGS 1:62500-scale Quadrangle for Dedham, MA 1919|1919-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/62500/MA_Dedham_352583_1919_62500_geo.pdf USGS 1:62500-scale Quadrangle for Duxbury, MA 1918|1918-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/62500/MA_Duxbury_462916_1918_62500_geo.pdf USGS 1:62500-scale Quadrangle for Duxbury, MA 1918|1918-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/MA/62500/MA_Duxbury_462918_1918_62500_geo.pdf

# The 10 oldest maps of New York city

$ usgsassist -a historic -l "New York, NY" | sort -t'|' -k2 | head -20 USGS 1:62500-scale Quadrangle for Morristown, NJ 1888|1888-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Morristown_255268_1888_62500_geo.pdf USGS 1:62500-scale Quadrangle for New Brunswick, NJ 1888|1888-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_New%20Brunswick_255290_1888_62500_geo.pdf USGS 1:62500-scale Quadrangle for Paterson, NJ 1888|1888-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Paterson_255310_1888_62500_geo.pdf USGS 1:62500-scale Quadrangle for Plainfield, NJ 1888|1888-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Plainfield_255320_1888_62500_geo.pdf USGS 1:62500-scale Quadrangle for Sandy Hook, NJ 1888|1888-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Sandy%20Hook_255362_1888_62500_geo.pdf USGS 1:62500-scale Quadrangle for Brooklyn, NY 1889|1889-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Brooklyn_8033200_1889_62500_geo.pdf USGS 1:62500-scale Quadrangle for Harlem, NJ 1891|1891-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Harlem_472515_1891_62500_geo.pdf USGS 1:62500-scale Quadrangle for Brooklyn, NY 1891|1891-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Brooklyn_8033120_1891_62500_geo.pdf USGS 1:62500-scale Quadrangle for Paterson, NJ 1892|1892-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Paterson_472458_1892_62500_geo.pdf USGS 1:62500-scale Quadrangle for New Brunswick, NJ 1893|1893-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_New%20Brunswick_255291_1893_62500_geo.pdf USGS 1:62500-scale Quadrangle for New Brunswick, NJ 1893|1893-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_New%20Brunswick_255292_1893_62500_geo.pdf USGS 1:62500-scale Quadrangle for Plainfield, NJ 1893|1893-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Plainfield_255321_1893_62500_geo.pdf USGS 1:62500-scale Quadrangle for Plainfield, NJ 1893|1893-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Plainfield_255323_1893_62500_geo.pdf USGS 1:62500-scale Quadrangle for Sandy Hook, NJ 1893|1893-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Sandy%20Hook_255363_1893_62500_geo.pdf USGS 1:62500-scale Quadrangle for Sandy Hook, NJ 1893|1893-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Sandy%20Hook_255364_1893_62500_geo.pdf USGS 1:62500-scale Quadrangle for Morristown, NJ 1894|1894-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NJ/62500/NJ_Morristown_255269_1894_62500_geo.pdf USGS 1:62500-scale Quadrangle for Brooklyn, NY 1897|1897-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Brooklyn_123118_1897_62500_geo.pdf USGS 1:62500-scale Quadrangle for Brooklyn, NY 1897|1897-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Brooklyn_123119_1897_62500_geo.pdf USGS 1:62500-scale Quadrangle for Brooklyn, NY 1897|1897-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Brooklyn_123121_1897_62500_geo.pdf USGS 1:62500-scale Quadrangle for Harlem, NY 1897|1897-01-01|https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Harlem_129718_1897_62500_geo.pdf

# Historic maps of Rochester from the 1800's

$ usgsassist -a historic -l "Rochester, NY" -v | jq -r '.items[] | select(.publicationDate | test("^18")) | .title' USGS 1:62500-scale Quadrangle for Ontario Beach, NY 1895 USGS 1:62500-scale Quadrangle for Ontario Beach, NY 1899 USGS 1:62500-scale Quadrangle for Ontario Beach, NY 1899 USGS 1:62500-scale Quadrangle for Ontario Beach, NY 1899 USGS 1:62500-scale Quadrangle for Rochester, NY 1895 USGS 1:62500-scale Quadrangle for Rochester, NY 1898 USGS 1:62500-scale Quadrangle for Rochester, NY 1898 USGS 1:62500-scale Quadrangle for Rochester, NY 1898 USGS 1:62500-scale Quadrangle for Rochester, NY 1898 USGS 1:62500-scale Quadrangle for Rochester, NY 1898

# An preview image of these maps

$ usgsassist -a historic -l "Rochester, NY" -v | jq -r '.items[] | select(.publicationDate | test("^18")) | .previewGraphicURL' https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Ontario%20Beach_148062_1895_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Ontario%20Beach_148065_1899_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Ontario%20Beach_148064_1899_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Ontario%20Beach_148063_1899_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Rochester_148337_1895_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Rochester_148339_1898_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Rochester_148345_1898_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Rochester_148344_1898_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Rochester_148340_1898_62500_tn.jpg https://prd-tnm.s3.amazonaws.com/StagedProducts/Maps/HistoricalTopo/PDF/NY/62500/NY_Rochester_148343_1898_62500_tn.jpg # Now grab these images and make a contact sheet $ usgsassist -a historic -l "Rochester, NY" -v | \ jq -r '.items[] | select(.publicationDate | test("^18")) | .previewGraphicURL' | \ while read url ; do wget -q $url ; done $ montage *_tn.jpg contact.jpg

Fun, right? Here's the script. Happy Hacking!

#!/bin/bash

##
## Tools to work with the USGS
##

PER_PAGE=50

if [ -f  $HOME/.config/usgsassist/config ] ; then
  . $HOME/.config/usgsassist/config
else
  echo "Missing: ~/.config/usgassist/config file"
  exit
fi

usage() {
  cmd=$(basename $0)
  echo "Usage: $cmd -a topos -l location "
  echo "Usage: $cmd -a historic -l location "
  echo "Usage: $cmd -a geobox -l location"

  exit 1
}

summarize_json() {
  if [ "$verbose" = "yes" ] ; then
    jq '.items[]' | sed 's/^{/,{/' | sed '1s/^,//'
  else
    jq -r '.items[] | .title + "|" + .publicationDate + "|" + .downloadURL' | sed -E  's/^(USGS )?US Topo 7.5-minute map for //'
  fi
}

get() {
  dataset="$1" ; shift
  bb="$1" ; shift
  offset="$1" ; shift

  curl -s -G \
       --data-urlencode datasets="$dataset" \
       --data-urlencode bbox="$bb" \
       --data-urlencode offset="$offset" \
       --data-urlencode max="$PER_PAGE" \
         https://tnmaccess.nationalmap.gov/api/v1/products | tee $HOME/.usgs.last | summarize_json
}


all() {
  dataset="$1" ; shift
  bb="$1" ; shift

  if [ "$verbose" = "yes" ] ; then
    echo '{ "items" : [ '
  fi

  get "$dataset" "$bb" 0

  total=$(cat $HOME/.usgs.last | jq .total)
  remaining=$((total - PER_PAGE))

  if [ $remaining -gt 0 ] ; then
    pages=$(((remaining / PER_PAGE) + 1))
    for page in $(seq 1 $pages) ; do
      offset=$((page * PER_PAGE))

      if [ "$verbose" = "yes" ] ; then
        echo ","
      fi

      get "$dataset" "$bb" "$offset"
    done
  fi

  if [ "$verbose" = "yes" ] ; then
    echo '] }'
  fi
}


while getopts ":a:l:hv" o; do
  case "$o" in
    a) action=$OPTARG ;;
    l) loc=$OPTARG ;;
    v) verbose=yes ;;
    *|h) usage ;;
  esac
done

case "$action" in

  topos)
    if [ -z "$loc" ] ; then
      echo "Missing -l location"
      exit
    fi
    bb=$(usgsassist -a geobox -l "$loc")

    all "US Topo Current" "$bb"
    ;;
  historic)
    if [ -z "$loc" ] ; then
      echo "Missing -l location"
      exit
    fi
    bb=$(usgsassist -a geobox -l "$loc")

    all "Historical Topographic Maps" "$bb"
    ;;


  geobox)
    if [ -z "$loc" ] ; then
      echo "Missing -l address"
      exit
    fi

    bounds=$HOME/.usgs.bounds
    curl -s -G "https://maps.googleapis.com/maps/api/geocode/json" \
         --data-urlencode address="$loc" \
         -d key=$GOOGLE_MAPS_API_KEY  > $bounds
    if [ "$verbose" = "yes" ] ; then
      cat $bounds
    else
      ne_lat=$(cat $bounds | jq '.results[0].geometry.viewport.northeast.lat')
      ne_lng=$(cat $bounds | jq '.results[0].geometry.viewport.northeast.lng')
      sw_lat=$(cat $bounds | jq '.results[0].geometry.viewport.southwest.lat')
      sw_lng=$(cat $bounds | jq '.results[0].geometry.viewport.southwest.lng')
      echo "$ne_lng,$ne_lat,$sw_lng,$sw_lat"
    fi
    ;;

  *) usage ;;
esac

Friday, January 13, 2023

Digital Redneck Engineering: a Trip Timer for the Mazda CX-5

We recently leased a Mazda CX-5. While it surprised us with it's comprehensive feature set (heads up display, baby!), it was missing one important aspect: a simple trip timer. This is nothing more than a stopwatch that starts when the car is turned on. The idea is that you can glance at it to see just how long you've been stuck in traffic, or just how quickly you got home from a daycare run.

Fortunately of all the features offered by a car, this is an easy one to add on. I know this because our Acura RDX had the same issue. Having built my own timer in the past, I had a good idea as to how to do this again.

First off, I visited adafruit.com and did a bit of shopping. I was looking for the components I'd need to create a simple programmable display. It didn't take long before I found the ESP32-S2 TFT Feather. This combined an ESP32 chip with a tiny, but sharp, display. It looked it would be perfect for a timer. I purchased one and patiently waited for it arrive.

When the board arrived I put Circuit Python 8 on it by following these instructions. The installation process went smoothly and I was able access the top level web page offered by the web workflow. Unfortunately, my luck stopped there and I wasn't able to access the Web REPL or file browser. While I wanted to try these features, I realized I didn't actually need them for this project so I gave up on trying to use the Web Workflow.

Starting with a simple Hello World example, I was able to create a code.py file that implemented my timer. Here it is in all its glory:

##
## Shows how long the car has been turned on for
##

import time
import board
import terminalio
from adafruit_display_text import bitmap_label

scale = 5

started = time.monotonic();
text_area = bitmap_label.Label(terminalio.FONT, text="---", scale=scale)
text_area.x = 0
text_area.y = 60
board.DISPLAY.show(text_area)

def digit(value):
    return str(value) if value > 10 else "0" + str(value)

def time_string(started):
    now = time.monotonic()
    t = round(now - started)
    ss = t % 60
    mm = (t // 60) % 60
    hh = (t // (60*60)) % 60
    return digit(hh) + ":" + digit(mm) + ":" + digit(ss)


while True:
    text_area.text = time_string(started)
    time.sleep(1);

Deploying this code to the board is easy: I connected the ESP32 to my laptop via a USB-C cable, mounted it as a drive, and copied code.py into the root directory. Copying the file into places causes the board to reboot and execute code.py. It's all very slick and coder friendly.

The trickiest part of the process was installing the various library dependencies that code.py imported. I did this through trial and error. The board would run code.py, and display an error message as to which library was missing. I'd copy the relevant library from the bundle I'd downloaded, and repeat the process.

Eventually my code ran without issue. I grabbed a cigarette lighter* to USB-A adapter, USB-C cable and some mounting putty and brought it out our car. I then quickly rigged up this demo:

Success!

I'm in awe of the Adafruit ESP32-S2-TFT. For $24, I've now own tiny computer that includes a brilliant color screen, a built in neopixel and WiFi support. Trivially, I'm able to program it over the air using Python, and with effort I could almost certainly turn it into a forth or scheme computer. My timer scratches only the surface of these capabilities. I'm not sure whether I'll build a v2.0 of my timer, or use the board in another project altogether. But I almost certainly need to do something with this device, it's amazing.


*Kids today must be baffled as to why the strange shaped power plug on a vehicle is a called a cigarette lighter. Have no fear, YouTube can explain. I have a vague memory of being a kid figuring out that this oddly shaped knob could pressed in and would eventually get red hot. Perfect for lighting up your cigarette. Crazy, right?

Wednesday, January 11, 2023

Accessing an SD Card on Windows from WSL2

Every so often I find that I want to access a Micro SD card from within Linux on my Windows WSL2 setup. I put the card in my laptop and am pleased when Windows announces the new D: drive is available. And then the confusion begins: how do I access this drive from a WSL2 Ubuntu session?

The C: drive is automatically available to me in /mnt/c; not so with D: and /mnt/d.

A Google search inevitably takes me this page which talks about using wsl --mount. While promising, this never works for me.

Often, by now, I've decided I didn't really need to access the SD card *that* badly and give up.

But, it turns out there's a trivial solution! The following mount command is all I need:

  sudo mount -t drvfs 'D:' /mnt/d

Once that command is issued, the SD card files are available under /mnt/d, and are accessible like any other files on Linux. This works for any drive letter, not just 'D'.

Notably, this isn't SD card specific. I just connected an Adafruit ESP32-S2 TFT Feather micro-controller to my laptop and Windows recognized it as a drive.

I issued the same mount command to make this visible to Linux:

$ ls /mnt/d
ls: cannot access '/mnt/d': No such device
$  sudo mount -t drvfs 'D:' /mnt/d
$ ls /mnt/d
'System Volume Information'   boot_out.txt   code.py   lib   settings.toml

And success! Now, if I can just remember to check the blog for this solution before I give up...

Thursday, January 05, 2023

Starting 2023 Off Right: Exploring Huntley Meadows

If there's a better way to start a year than with a New Years Day Hike, I surely haven't found it.

The weather cooperated and we had an awesome hike at Huntley Meadows with G, his Mom, Shira and our little one. Apparently enough time has passed since my last hike through Huntley Meadows that I'd forgotten just how delightful a location it is.

The well packed trails and boardwalk meant that Shira and my Sister-in-Law could bring strollers for the little ones, though G spent most of the hike walking.

We had some delightful flora and fauna sightings, including an impressive cluster (or was it a troop?) of what appeared to be turkey tail mushrooms. We spotted a number of Northern Pintail ducks. At first glance, these looked like 'normal' ducks, but thanks to my kid friendly binoculars I could see that these were far more handsome. My photos don't do these guys justice.

We caught sight of a bale of turtle lined up sunning themselves. While this may be common, it always makes me smile whenever I see it.

Finally, we came across a patch of red berries, which Google tells me were rose hips. While they were fun to photograph, I wish I'd collected some for drying and tea making. I've since learned that rose hips are typically collected after the first frost, so it's wild edible that would be perfect to search out this time of year.

Here's to a 2023 filled with family, adventure and discovery!


Wednesday, January 04, 2023

Review: The Gift of Fear

While I enjoyed listening Gavin De Becker's The Gift Of Fear, I'm fairly certain Shira didn't appreciate it nearly as much. That's because I kept trying to recount the latest anecdote I'd heard from the text, and I'm sure it all fell felt hearing this second hand. I'd almost always end my attempted retelling with, 'babe, you've just got read the book.'

The Gift of Fear is Becker's prescription for staying safe in a world filled with hazards. Here's my very brief summary:

  • Fear is good.
  • Worry is bad.
  • Violence has warning signs.

While these concepts may appear provocative, I found Becker's arguments to be convincing.

Fear is good. Fear is one of the signals that our brain sends our body. Other less dramatic signals include curiosity, gut-feelings, intuition, worry and anxiety. Becker's suggestion is that these sensations are quite valuable, and should be respected like our other senses. That's not because they're mystical in nature, but because they are our own bodies communicating what our other senses have already learned.

Just like you dull your senses when you put on noise canceling headphones and walk through your neighborhood, you dull your senses when you write off, and ultimately ignore, worry, anxiety and fear.

Continuing the analogy, if you are strolling your neighbored and here a loud noise from behind, your first reaction would be to turn around and look to see if you are in danger. Becker calls for you to do the same thing when you get a 'bad feeling.' That is, acknowledge the feeling and use your other senses to determine what action you should take.

And finally, some sounds are programmed for us to take action. Years ago I was running at night and heard a sharp cracking noise, I instinctively took off like my life depended on it. And that's because it did. I happened to be steps away from a massive tree that gave way due to wet conditions. Fear, Becker argues, is a signal that deserves action first, analysis later.

Worry is bad. In a sense worry is a signal, so it's inherently useful. Respect it, unpack it and move on. But constant worry is a problem because it leaves no space for other signals to get through. If you worry every time you approach a specific intersection, then you can't depend on the fear signal getting through when you really should be concerned at that intersection.

If you find yourself in a regular state of worry, then it's time to take action to figure out why and take steps to alleviate this worry.

Violence has warning signs. Becker argues that nearly all violent events have markers, often times going back years. The employee or boy friend who acts violently had no choice but to show you months or even years of warnings. Much of The Gift of Fear goes through examples of these warning signs, though Becker makes the point that you need not memorize them; just listen to your intuition. Still, hearing these warning signs inoculates you to them, and makes recognizing them easier.

While I'm ready to recommend Becker's book to all who are college age and above, I do have some points to quibble with. At times, the book reads as a sort of advertisement for his mega-elite security firm, which may turn off some.

The book's 'Get off the X' approach to violence may also be a point of contention for some. 'Getting off the X' refers to the principle that the most urgent need in a dangerous situation is to get away from the threat. Becker's approach throughout The Gift of Fear embraces a similar idea. For example, the goal is to safely decouple yourself from a dangerous partner or employee. Becker doesn't explore what society should do with these problematic individuals, or how to assist the next partner or employer that may get tangled in this person's behavior. I think that's reasonable given the focus of the book, but it does raise some interesting ethical and sociological questions which go unanswered.

One area that I wish the book had explored more concretely was the actions people should or shouldn't take in preparation for violence. Becker leaves hints throughout the book on his perspective on this, but I wish he'd been more direct.

For example, Becker claims that armed guards at your company's entrance can reduce safety by giving the false impression that security is "handled" and that employees can ignore their fear signals. At the same time, he praises security infrastructure like key cards, and procedures like deactivating key cards when an employee is fired. Why is one action considered a step back, and the other a step forward?

He also laughs off the notion of a couple that gets concealed carry permits to protect themselves and others during a mass shooting. He explains that they are more likely to shoot themselves then the bad guy. On the topic of mass shootings, would Becker consider the Until Help Arrives training to deal with mass casuality incidents as feeding anxiety and wasting time focusing on an unlikely scenario? Or, would he praise it for arming citizens with critical skills that educate and thereby reduce worry?

And what about shelter in place drills for children? Are they an important and useful safety precaution like fire drills? Or, do they just fill kids with anxiety which will leave them less safe?

My reading of Becker is that actions that reduce worry and provide concrete skills are a good thing. Actions that serve to amp up concern should be avoided. But that still leaves a lot of gray areas. For example, could key carded doors not give the same "security is handled" impression that armed guards do?

When I casually looked at the book's description, I saw that it was released in 2017. So I was more than a bit surprised when I got to the end of the epilogue and it was signed, 'Gavin De Becker, 1998'. The epilogue starts with the statement that the book had been out for a year. So The Gift of Fear is now 26 years old. I have to say, it's aged well.

One clue to its age was the opening chapter, which seemed to be a mishmash of political dog whistles. Becker explains that everyone is impacted by violence and that the world is a dangerous place; that's the kind of messaging I'd expect to hear from gun-toting conservative neighbor. In the same chapter, he also calls out the ridiculous availability of hand guns; a talking point I'd expect to hear from my liberal neighbor. He includes statements like "the government isn't going to save you," a message straight out of the libertarian handbook. And yet, Becker proudly explains that he has worked with top federal agencies to help institute polices; these are the kind of claims I'd expect to hear from someone who believes Government can and should be a force for good.

It was refreshing to these opinions spilled out together, and I wonder how much push back Becker would have received if he'd tried to start a best seller today with such a collection of statements.

Another sign that the book was written in the late 90's is the lack of discussion on school and other mass shootings. The Columbine High School Shooting, widely considered to be the first of its kind, happened in 1998. Though, Becker's prediction that one horrific event is often advertisement for future events does indeed hold true.

There's also no discussion of terrorism, a topic that would be hard to ignore after 9/11/2001.

I had to smile as Becker mentioned the absurd fear that Americans have for 'foreign viruses.' Yeah, not so absurd now is it?

For most Americans, violence remains a sort of contradiction. In many respects, we are safer now than ever. Yet at the same time, countless Americans are impacted by violence on a daily basis. There's no silver bullet for navigating this paradox, yet The Gift of Fear appears to be a useful addition to our safety toolbox. That's because its core premise is that you already have its invaluable tools at your disposal, you just need to give yourself permission to use them.