As what as you like

  • Getting battery data from AirPods in macOS

    A recent feature request for Hammerspoon requested that we add support for reading battery information about AirPods (UK US).

    Unfortunately because their battery status is quite complex (two earbuds and the case), this information is not reported via the normal IOKit APIs, but with a bit of poking around in the results of class-dump for macOS High Sierra I was able to find some relevant methods/properties on IOBluetoothDevice that let you read information about the battery level of individual AirPods and the case, plus determine which of the buds are currently in an ear!

    So, the next release of Hammerspoon should include this code to expose all of this information neatly via hs.battery.privateBluetoothBatteryInfo() 😁

  • Happy 10th Birthday Terminator!

    Today marks 10 years since the very first public release of Terminator, a multiplexing terminal emulator project.

    I started working on Terminator as a simple way to get 4 terminals to not overlap on my laptop screen. In the following years it grew many features and attracted a userbase I am very proud of.

    As much as I would like to, I cannot claim most of the credit for Terminator surviving for a decade - I stepped away from the project a few years ago and handed the reigns over to Stephen Boddy at a very crucial time - gtk2 was becoming ever more obsolete and our work on a gtk3 port was very incomplete. Stephen has driven the project forward and it now has a very good gtk3 version :)

    So, thank you to Stephen and everybody else who contributed code/docs/translations/suggestions/bugs/etc over the last 10 years (you can see the most active folk here).

    I’d also like to note that according to Ubuntu’s Popularity Contest data, Terminator is installed on at least 56000 Ubuntu machines. Debian also has PopCon data, but the numbers there are a little less impressive ;)

    This was the first project of mine that reached any kind of significant audience, and is the first project of mine to have achieved a decade of active maintenance, so I am feeling pretty happy today!

  • USB Type C is awful

    Intentionally inflammatory title there, but there are some valid reasons to be annoyed at USB Type C.

    Firstly, I have discovered (the hard way) that although there are many cables on sale, the majority of Type C cables do not support even USB 3.0 speeds (so 5Gb/s) let alone USB 3.1gen2 (so 10Gb/s) speeds. They are actually USB 2.0 (so 480Mb/s) cables.

    I can understand that some devices with Type C connectors may only need USB 2.0 speeds, but for the cables to not all be USB 3.x seems crazy to me. Even Apple is doing this - the charging cables for MacBooks (12” and Pros) with Type C ports, only support USB 2.0 speeds. If I had to guess, I’d say it’s because they wanted the cables to be thin and easily bendable, which full USB 3.1 cables tend not to be.

    Secondly, unlike Type A, which marks USB 3.x cables by having blue plastic inside the connectors, there is no way to tell what speed a Type C cable is by looking at it.

    Thirdly, and perhaps most importantly, USB Type C is a vastly more powerful beast than previous versions - a modern Type C port can be capable of:

    • 40Gb/s Thunderbolt 3
    • DisplayPort
    • 10Gb/s USB 3.1gen2
    • 100W of (actively negotiated) power delivery in either direction

    The DisplayPort “alternate mode” can deliver 4K at 60Hz with USB3.1 at the same time, or 5K with USB2.0 at the same time, or 8K (compressed). When used as Thunderbolt, Type C can carry 5K video as well as the PCI data.

    So while one tiny connector can do a whole bunch of really impressive things, the cables are now expected to do vastly more than even USB3.0 Type A cables, let alone USB 2.0, and it seems like that advanced capability isn’t currently aligned with the history of USB as being an ultra-cheap, mass market affair.

    Various awesome folk have put together a spreadsheet of the chargers/cables they’ve tested, and it seems like a serious chunk of the Type C cables currently on the market, are junk. This is bad for everyone, especially users, who can buy what looks like the right cable, only to discover that their devices either don’t work at all, or work to slowly, or won’t charge properly.

    This post exists because I needed a USB3.0, three metre, Type A to Type C cable, and I bought one on Amazon, only to discover that it only supported USB2.0. After far too much searching, I eventually found an Anker cable which meets my requirements:

  • Home networking like a pro - Part 1 - Network Storage

    Introduction

    This is part one in a series of posts about some hardware I recommend (or otherwise!) for people who want to bring some semi-professional flair to their home network.

    The first topic is storage - specifically, Network Attached Storage.

    Background

    For the last few years, I was running a Mac Mini with two 3TB drives in a RAID1 array in a LaCie 2big Thunderbolt chassis (US UK), with the Mac running macOS Server to provide file sharing (AFP and SMB), and Time Machine backups for the rest of the network.

    This was a very nice solution, in that the Mac was a regular computer, so I could make it do whatever I wanted, but it did have the drawbacks that the Thunderbolt chassis only had two drive bays, and I had trouble getting the Mac to run reliably for months at a time (I ran into GPU related kernel panics, perhaps because it was attached to a TV rather than a monitor).

    Around the time I was selecting the Mac/LaCie, most NAS devices in a similar price range were very underpowered ARM devices, and could do little more than share files, but in 2017 almost all NAS devices are much more powerful x86 devices that often have extensive featuresets (e.g. running containers, VMs, hardware accelerated video transcoding, etc.) so I decided it was time to switch.

    Solution

    I ended up choosing a Synology DS916+ (US UK), popped one of the 3TB drives (Western Digital Red (US UK)) out of the LaCie and into the Synology, and set about migrating my data over. I then moved the other drive, and put in two more 3TB drives, all of which are running as a single Synology Hybrid RAID volume with a BTRFS filesystem (note that the Hybrid RAID really seems to just be RAID5).

    I configured the Synology to serve files over both AFP and SMB, and enabled its support for Time Machine via AFP. I was also able to connect both of its Ethernet ports to my switch (a ZyXEL GS1900 24 port switch, which I will cover in an upcoming post) and enabled LACP on each end to bond the two connections into a single 2Gb link.

    So, how did it work out?

    The AFP file sharing is great, and works flawlessly. SMB is a little more complex, because recent versions of macOS tend to enforce encryption on SMB connections, which makes them go much slower, but this can be disabled. I tested Time Machine over SMB, which is officially supported by Synology, but is a very recent addition, and it proved to be unreliable, so that is staying on AFP for now.

    Something I was particularly keen on, with the Synology, was that it has an “app store” and one of the available applications is Docker. I was running a few UNIX daemons on the Mac Mini which I wanted to keep, and Docker containers would be perfect for them, however, I discovered that the version of Docker provided by Synology is pretty old and I ran into a strange bug that would cause dockerd to consume all available CPU cycles.

    For now, the containers are running on an Intel NUC (which will also be covered in an upcoming post) and the Synology is focussed on file sharing.

    Open Source

    Synology’s NAS products are based on Linux, Samba, netatalk and a variety of other Open Source projects, with their custom management GUI on top. They do publish source, but it’s usually a little slow to arrive on the site, and it’s not particularly easy (or in some cases even possible) to rebuild in a way that lets you actively customise the device.

    Conclusion

    Overall, I like the Synology, but I think if I’d known about the Docker issue, I might have built my own machine and put something like FreeNAS on it. More work, less support, but more flexibility.

    The recent 5-8 drive Synologies now support running VMs, which seems like a very interesting prospect, since it ought to isolate you from Synology’s choices of software versions.

  • Hyper Key in macOS Sierra with Karabiner Elements

    Over the last few years, various people have used Karabiner to remap Caps Lock to cmd+shift+opt+ctrl, which is such an unusual combination of modifier keys, that it effectively makes Caps behave as a completely new modifier (which we have collectively called “Hyper”, in reference to old UNIX workstation keyboards).

    And for a time, it was good.

    Then came macOS Sierra, which changed enough of the input layers of its kernel, that Karabiner was unable to function. Thankfully, Karabiner’s author, Fumihiko Takayama, began work on a complete rewrite of Karabiner, which is currently called Karabiner Elements.

    Initially, Elements only supported very simple keyboard modifications - you could swap one key for another, but that was it. Various folk quickly got to work offering quick hacks to get a Hyper key to work, and others started to try to work around the missing support, with other tools.

    I’m very glad to say that it is now possible to do a proper Hyper remap with Karabiner Elements (and to be clear, none of this is my work, all credit goes to Fumihiko).

    Here’s how you can get it:

    • Download and install https://pqrs.org/latest/karabiner-elements-latest.dmg
    • Launch the Karabiner Elements app, go to the Misc tab and check which version you have, if it’s less than 0.91.1, click either Check for updates or Check for beta updates until you get offered 0.91.1 or higher, then install that update and re-launch the Karabiner Elements app.
    • You probably want to remove the example entry in the Simple Modifications tab.
    • Edit ~/.config/karabiner/karabiner.json
    • Find the simple_modifications section, and right after it, paste in:
    "complex_modifications": {
        "rules": [
            {
                "manipulators": [
                    {
                        "description": "Change caps_lock to command+control+option+shift.",
                        "from": {
                            "key_code": "caps_lock",
                            "modifiers": {
                                "optional": [
                                    "any"
                                ]
                            }
                        },
                        "to": [
                            {
                                "key_code": "left_shift",
                                "modifiers": [
                                    "left_command",
                                    "left_control",
                                    "left_option"
                                ]
                            }
                        ],
                        "type": "basic"
                    }
                ]
            }
        ]
    },
    
    • As soon as you save the file, Elements will notice it has changed, and reload its config. You should immediately have a working Hyper key 😁

    If you’re not confident at your ability to hand-merge JSON like this, and don’t need anything from Elements other than the basic defaults, plus Hyper, feel free to grab my config and drop it in ~/.config/karabiner/.

    Supplemental note for High Sierra

    I’ve only tested this very briefly on High Sierra, but I had to disable SIP to get the Elements .kext to load. I’m not quite sure what’s going on, but I reported it on GitHub. (Note that you can re-enable SIP after the kext has been loaded successfully once)

    Update

    Many people like to turn Caps into Hyper, but also have it behave as Escape if it is tapped on its own. As of Karabiner Elements 0.91.3 this appears to be possible by adding this to the manipulator:

    "to_if_alone": [
        {
            "key_code": "escape",
            "modifiers": {
                "optional": [
                    "any"
                ]
            }
        }
    ],
    

    (thanks to Brett Terpstra for the sample of this