Gerrit Niezen

Maker of open-source software and hardware.

At the beginning of the month, I mentioned that I started doing the Highlight course, an online course based on the book Make Time by Jake Knapp and John Zeratsky. I just completed the course, and part of the final module was to reflect back on the month, with some questions I answered below. If you'd like to know more about some of the specific tactics I mentioned below, get in touch @gendor@merveilles.town on Mastodon.

What did you want to make time for?

I wanted to make time for my side projects, which includes building electronics, hydroponics and growing my own food, permaculture, and getting more involved with climate action in my local community.

Were you able to make time for it?

I was able to spend an evening each week on an online permaculture course. I started growing sprouts using a mason jar strainer lid that I printed on my 3D printer. I started a garden diary, installed a rainwater harvesting system and made my own cleaning products.

I also made much faster progress than usual on a bunch of projects at work.

What is your “tactic stack”? (Your 5-7 essential tactics.)

  • Write it down
  • Schedule your highlight
  • Put your toys away
  • Might Do list
  • Make your bedroom a bed room

What’s an unexpected challenge you faced in making time?

There are some of my side projects, like hydroponics, and getting more involved with climate action, that ranked pretty high on my ideal priority during stack rank, but that I still haven't been able to make time for. Maybe I need to try and Explode my Highlight, and then combine the Might Do list with the Burner list?

What’s an unexpected success?

I drink a lot of coffee. A lot. Experimenting with caffeine use seemed like a non-starter due to my dependence, but after trying Maintaining Altitude with Green Tea, I'm more confident that I can try some of the other caffeine-related tactics.

I've tried various attempts at a distraction-free phone in the past, but finally deleting Instagram and other social media from my phone made it so much easier to also Make my Bedroom a Bed Room.

How is your life different now than it was at the beginning of the course?

I feel like I'm less anxious and more present. I'm excited to keep this going and make time for more things, although I'm a bit concerned that I will fall off the wagon again, so to speak. I'm hoping that the Make Time community will keep me on track.

How will you use the Make Time framework in the future?

I'm looking forward to trying other tactics, like the Burner List and Friendly Social Jujitsu. I've found that the Make Time app (on Android) has been really helpful in keeping me going, by providing both opportunities for writing down and scheduling my highlight, as well as reminding me to reflect at the end of the day.


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day35

This is a follow-on to Part 1 and Part 2 of my adventures in connecting to Android devices over MTP using Node.js, on Windows.

While compiling the Node.js native module, I got the following error:

Macro definition of snprintf conflicts with Standard Library function declaration

Searching StackOverflow led to this solution, which I added to the libmtp source code:

#if _MSC_VER < 1900
#define snprintf _snprintf
#endif

I also kept on getting a “Module not found” error, until I re-read my own post and used Dependency Walker to figure out that for some reason my .node file is looking for libmtp-9.dll.dll instead of libmtp-9.dll. 🤷‍♂️️ I also had to copy libusb-1.0.dll into the same folder, as it was looking for that too.

Finally, like magic, I was able to connect to a device on Windows over MTP with my own Node.js library using libmtp, instead of the Windows MTP implementation that can only be accessed through Windows Explorer or the Windows APIs.

And I just submitted a PR to get Windows builds fixed in the upstream libmtp library.

Next step: Getting it compiled for 32-bit Windows using i686-w64-mingw32 and/or i686-mingw32


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day34 #libmtp #Node.js

So even though I managed to get libmtp compiled under Windows, I can't get it to work with Node.js. I've decided to take the same approach as what I did with ffmpeg's libavutil library, and cross-compile it under Linux instead.

To do this, I needed mingw64 on my Linux machine:

sudo apt-get install mingw-w64
sudo apt-get install mingw-w64-tools

It doesn't look like libusb has been pre-compiled for mingw64 on Linux, so I had to do the following:

git clone https://github.com/libusb/libusb.git
 git checkout v1.0.23
./autogen.sh
./configure --host=x86_64-w64-mingw32
make
DESTDIR=$HOME/Code/mingw64/ make install

This installs the libusb library (compiled for Windows) under $HOME/Code/mingw64/. Then I had to configure libmtp to use our Windows libusb build:

PKG_CONFIG_PATH=$HOME/Code/mingw64/usr/local/lib/pkgconfig  ./configure --host=x86_64-w64-mingw32
make

Again I had to fix unicode.c to get it working. I should submit this work as a PR to libmtp.

Next step: Try to get this working in as a native Node.js addon.

For reference: http://www.tinc-vpn.org/examples/cross-compiling-64-bit-windows-binary/


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day33 #libmtp

In preparation for the Stay-at-home TH/NG Jam next Friday, I thought I'd at least check if I can get the basic tech, including Web NFC, working.

Web NFC is an open specification, but so far it is only supported on Chrome for Android behind a feature flag, meaning you'll have to enable experimental web platform features in chrome://flags. It has also been available as an origin trial since Chrome v81.

First, we need a basic index.html file:

<html>
  <head>
    <title>Smart Paper Maps</title>
    <script src="main.js"></script>
    <link rel="stylesheet" type="text/css" href="main.css">
  </head>
  <body>
    <button id="scan" class="buttons">Scan</button>
    <p id="p1" class="text"></p>
  </body>
</html>

All we're doing is linking to our main.js and main.css files, and setting up a button and a <p> section that we can use to display text. Our main.css just makes the button and text a bit bigger to make it easier to tap and read:

.buttons{
    height:200px;
    width:200px;
    font-size: xx-large;
}

.text{
  font-size: xx-large;
}

And finally, the actual code that reads the NFC tags:

document.addEventListener('DOMContentLoaded', event => {
  const scanButton = document.getElementById('scan');
  const reader = new NDEFReader();
  
  scanButton.addEventListener('click', async () => {
    try {
      console.log('Scanning..');
      await reader.scan();
    } catch(e) {
      console.error("Error: ", e);
    }
  });
  
  reader.onreading = event => {
    console.log('Event:', event);
    document.getElementById("p1").innerHTML = event.serialNumber;
  };
});

We wait for the page to finish loading, initialise the NFC tag reader module NDEFReader(), and wait for the “Scan” button to be clicked. When we click the button, the browser will prompt for permission the first time. Once permission is granted, it will start scanning for NFC tags, and display the serial number when a tag gets read.

Because Web NFC requires an HTTPS Server, you'll have to set up a basic one to get this working. I'm using Node.js 12, and saved the following as simple-http-server.js:

const https = require('https');
const fs = require('fs');
const express = require('express');

const options = {
  key: fs.readFileSync('newkey.key'),
  cert: fs.readFileSync('newkey.crt')
};
const app = express();
app.use(express.static(__dirname));

https.createServer(options, app).listen(8080);

Do an npm install to install the Express server module, and set up the SSL keys using:

openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout newkey.key -out newkey.crt

Then run it with node simple-http-server.js. If you don't see any errors, you did it right. Go to <your computer's IP address>:8080 to access the page. You'll see some security warnings that you'll have to acknowledge, since we created our own self-signed keys.

I want to be able to view and debug my phone on my computer. Luckily, Chrom(ium) and Android makes this really easy. First, enable developer options on your Android phone and plug in your device via USB. To enable remote debugging, go to chrome://inspect/#devices in Chrom(ium) on your computer. You should be able to see your phone under Remote Target, and can then click on Inspect under the right browser tab to view your phone screen and the Chrome developer tools.

Hopefully, if everything is working, you'll see the following when you press the scan button and move over an NFC tag:


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day32

A week ago I saw this post on Instagram:

I attended and presented a workshop at Thingscon in Berlin in 2014, and it was one of the best conference experiences I've had. I haven't had a chance to attend it since, but have been keeping an eye on their Instagram feed for interesting events.

I really like the idea of this Stay-at-Home TH/NGS Jam:

Physical connection in time of virtual gathering

With most of my family and friends living overseas, I've been wanting to introduce more physicality into virtual connections for a long time. This seems like a great opportunity to both work on some ideas to make it happen, and to learn from others doing the same thing.

One idea would be to draw a map of a someone's home, and stick NFC tags on each room. You can then build a form of virtual “hide-and-seek”, where the remote person can state that they're in a specific room by linking to one of the tags, and you use a mobile phone to scan these tags and find out which “room” they're in. While too basic for adults, I think this could be fun for a toddler and their grandparents.

The same concept can be used for a company that works from home, where the video conferencing software may indicate which people are in each video chat, by linking these video chats to specific tags. To find out who is busy, or maybe hanging around the virtual water cooler, you scan a paper map of the virtual office.

One option would be to use Web NFC, a new technology available in Chrome on Android (in an origin trial since v81) that allows for the reading and writing of NDEF data from NFC tags. That simplifies the programming of this project to building a website.

I've already ordered some NFC tags from eBay to play with, and may even integrate my Espruino Pixl.js, a Bluetooth-enabled smart LCD that is NFC-capable.


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day31

I've mentioned previously that I started doing yoga using the Peloton app at the beginning of April. Note that I've never done any form of yoga before in my life. I found joining a yoga class too intimidating, so being able to learn the basics from the comfort of my living room is great. I've now done nine workouts, which averages to about once a week. Today I did my first 30 minute session, and I found it just as enjoyable as the 20 minute sessions I've done previously.

I'm using my wife's yoga mat, and bought some yoga blocks off eBay. All that's needed for most sessions is a mat, blocks and a blanket. Any blanket or throw will do. I've seen some sessions that require a yoga strap, but I've not needed it yet.

If I do it first thing in the morning, it really sets the tone for the day and helps me to calm my mind. I'm also learning how to stretch my body, which I've usually just considered as something to move my head from place to place. I hope I can keep this going – so far it's been intrinsically motivating, as in I haven't had to force myself to do it.


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day30

I've been growing sprouts as part of the permaculture course I mentioned in previous posts. The first time round I grew alfalfa sprouts in a mason jar, using a piece of cloth held together with a rubber band as a lid. The cloth didn't drain that easily, so I wanted something a little bit more suited to the task.

I recently got hold of some mung beans to grow proper bean sprouts, and decided to 3D print a sprout growing mason jar strainer I found on prusaprinters.org.

So far it's been working great, and I'll be printing another one with smaller holes for the alfalfa seeds as well.


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day29

I've known for a while that the water in a can of chickpeas, also called aquafaba or chickpea brine, can be used as an alternative to egg whites, but never actually tried it. Today I was making some hummus, and saved the chickpea water to attempt to make a chocolate mousse recipe I found online.

The only thing I'm regretting is that I haven't tried this sooner. It only requires three ingredients:

  • aquafaba / chickpea water
  • chocolate pieces/chips
  • cocoa powder

If you put aquafaba (120mL, the amount in a can of chickpeas) in a bowl and refrigerate it for 10 minutes, it takes less than 10 minutes (depending on the quality of the aquafaba) to whip it up with an electric mixer that it forms stiff peaks. Then you add 100g melted (and cooled down) chocolate chips while still mixing, a tablespoon or two of cocoa powder and continue mixing until everything's combined. Spoon it into glass cups, put it in the fridge for 30 minutes and you've got a delicious chocolate mousse (that doesn't taste like chickpeas at all!).


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day28

Last week our toilet started filling very slowly after a flush. I opened up the cistern and removed a screw cap from the inlet valve. I cleaned it and put it back, not realising that there was a small diaphragm washer that fell out and got flushed the next time I pulled the lever. Now the toilet was not stopping when filling. Oops.

After finding a brand name (Siamp), i was able to identify the actual model: a Compact 99B bottom entry inlet valve. Turns out you can't buy them from most of the DIY stores in the UK, but the replacement diaphragm washers can be found everywhere. These washers appear to be quite prone to wear and tear, and need to be replaced every so often.

I ordered a new diaphragm washer off eBay for £2.75 (including P&P), and a couple of days later it arrived. I replaced it, but the inlet valve still wouldn't stop filling. I watched a bunch of instructional videos on YouTube, all related to replacing the diaphragm washer of this specific model of inlet valve.

Even after making sure each of the various notches were correctly aligned, the inlet valve would not stop filling. I finally accepted that I'll have to replace the whole inlet valve, and came across this post suggesting an alternative brand that's more readily available and comes with a brass shank.

We picked up the new inlet valve from Click & Collect at Screwfix the next day. I installed the valve, only to have it leak out of the bottom of the cistern. Turns out there's an uneven bump next to the hole in the cistern that prevents the rubber seal from fitting properly. After re-fitting the inlet valve a bunch of times, I finally managed to get a proper seal by using the backnut from the old valve that could be tightened using a spanner.

Am I a plumber now?


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day27

A couple of days ago I mentioned that I'm attempting to compile libmtp under MSYS2/MINGW64. Steps so far:

  • Install MSYS2
  • Do pacman -Syuu repeatedly after first start until everything is up to date
  • Install git: pacman -S git
  • Install base-devel for basic development utilities
  • install mingw-w64-x86_64-toolchain (as we need mingw-w64-x86_64-gcc to not get _spawnv errors, see https://github.com/libimobiledevice/libplist/issues/136)
  • Install mingw-w64-x86_64-libiconv
  • Install mingw-w64-x86_64-libusb
  • Remember to run autogen.sh before running ./configure
  • Run make

Some useful MSYS2-specific things:

  • Use cd /c/ to get to the C: drive
  • pacman -S to install, -R to remove and -Ss to search
  • To access Windows path (e.g. to run node/npm, which can't be installed in MSYS2), add -use-full-path to the mingw64 app shortcut, or set environment variable MSYS2_PATH_TYPE to inherit

Now, after all of this I still got the following error:

unicode.c: In function 'utf16_to_utf8':
unicode.c:91:23: error: 'PTPParams' {aka 'struct _PTPParams'} has no member named 'cd_ucs2_to_locale'
   91 |   nconv = iconv(params->cd_ucs2_to_locale, &stringp, &convlen, &locp, &convmax);
      |                       ^~
unicode.c: In function 'utf8_to_utf16':
unicode.c:126:23: error: 'PTPParams' {aka 'struct _PTPParams'} has no member named 'cd_locale_to_ucs2'
  126 |   nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen, &unip, &convmax);

Turns out, it's a known issue. Based on a potential fix linked to in that GitHub issue, I was able to write a fix for a different file:

diff --git a/src/unicode.c b/src/unicode.c
index 2adc94e..b14274b 100644
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -87,12 +87,14 @@ char *utf16_to_utf8(LIBMTP_mtpdevice_t *device, const uint16_t *unicstr)
   size_t convmax = STRING_BUFFER_LENGTH*3;

   loclstr[0]='\0';
+  #if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
   /* Do the conversion.  */
   nconv = iconv(params->cd_ucs2_to_locale, &stringp, &convlen, &locp, &convmax);
   if (nconv == (size_t) -1) {
     // Return partial string anyway.
     *locp = '\0';
   }
+  #endif
   loclstr[STRING_BUFFER_LENGTH*3] = '\0';
   // Strip off any BOM, it's totally useless...
   if ((uint8_t) loclstr[0] == 0xEFU && (uint8_t) loclstr[1] == 0xBBU && (uint8_t) loclstr[2] == 0xBFU) {
@@ -121,7 +123,7 @@ uint16_t *utf8_to_utf16(LIBMTP_mtpdevice_t *device, const char *localstr)

   unicstr[0]='\0';
   unicstr[1]='\0';
-
+  #if defined(HAVE_ICONV) && defined(HAVE_LANGINFO_H)
   /* Do the conversion.  */
   nconv = iconv(params->cd_locale_to_ucs2, &stringp, &convlen, &unip, &convmax);

@@ -130,6 +132,7 @@ uint16_t *utf8_to_utf16(LIBMTP_mtpdevice_t *device, const char *localstr)
     unip[0] = '\0';
     unip[1] = '\0';
   }
+  #endif
   // make sure the string is null terminated
   unicstr[STRING_BUFFER_LENGTH*2] = '\0';
   unicstr[STRING_BUFFER_LENGTH*2+1] = '\0';

Lo and behold, I got it to compile!


I’m publishing this as part of 100 Days To Offload. You can join in yourself by visiting https://100daystooffload.com.

#100DaysToOffload #day26 #libmtp

Enter your email to subscribe to updates.