Botswana Trip

If you have landed here, it’s either because I’ve bored you rigid about photography and foisted the link on you directly, or you’ve googled something obscure like ‘Botswana and Tatooine’ and are wondering what goggles to pack for your own trip.

The TL;DR version: no matter how long you are staying, pack for about 3 days. Assuming you don’t fancy 40 degrees Celcius in the shade and are going in winter, take a wind-proof coat, a warm hat, and something to cover your nose and mouth. Maybe not goggles though: the lions will assume you’re an idiot and bite your head off.

Packing and Clothes

Packing for this trip turned out to be something of an art form. As most of the camps in the Okavango Delta are very remote you will likely need to travel by light aircraft, which imposes a 20kg total luggage limit; the bags also have to be soft, so no wheelie cases. If the planes are busy (ours weren’t), you can look forward to being weighed with your bags. I’m not entirely sure what happens if you exceed a limit on a busy flight. Maybe you have to travel on your own when you’re thinner.

My camera bag weighed 7kg, which left me with a bit of a struggle to pack everything else in.

I bought a 50 litre holdall which turned out to be a little small, coming in at 9kg fully packed, with enough spare capacity to buy a postcard or a nice sheet of A4. I really regretted not taking a GoreTex shell that I didn’t have room for. The temperature for the morning drives was around 10 degrees Celcius, which started to feel pretty bloody cold after half an hour: while my clothes were warm enough, they weren’t wind-proof. The jeeps at different camps were kitted out with a variety of blankets, fleecy ponchos (if you’ve gotten past the part where you might get weighed in front of the pilot and the other passengers, you can see that these trips don’t really cater for your vanity) and blankets. I took a peaked cap, but could have done with something warmer. I also missed the part where our travel agent recommended taking lip balm. I expect my lips will grow back at some point.

All of the camps we stayed at do laundry to accommodate the luggage limitations; you may need to wash your smalls though. I guess close encounters with apex predators might have some unintended consequences in that department. It’s a weird thing to get your head around, but you probably only need to pack for about 3 days, regardless of how long you’re staying.

Now we get on to the juicy part: what to wear.

Oh. My. God.

Lots people were dressed like… Let’s say a paratrooper crossed with Crocodile Dundee – except that they were mainly in their 60s and and from Surrey. I admit that I packed what I jokingly call my high performance trousers, a pair of middle-age affirming Rohans that I bought nearly 20 years ago. These have been quite useful for other trips down the years as they are fast drying (or what the Rohan blurb would probably call something like ‘UV activated surfactant wicking’, under a picture of someone rugged pointing meaningfully at the horizon). For this holiday, the most active we got was climbing into the jeeps. If your trousers need to be fast drying, it’s most likely because you spilled some white wine on them.

None of the big cats can see in colour [well, they have very limited colour perception], so wearing your army issue greens and browns is largely pointless. I asked two of our guides about this separately and they both agreed. One, a former soldier, joked about having to take cover. If your last line of defence is pattern dispersal, you’re screwed. The only rule is ‘not very bright’: if you are shuffling around in the jeep in your disco shirt, it may break the illusion that the vehicle is a single entity which the cat will ignore. Other colours may have a bearing on insects: wearing black will obviously make you sweat like one of these:

Warthogs – ISO 200; F5.6; 1/250 second

The final packing observation is about dust. The delta is in the Kalahari Basin so everything that isn’t wet is covered in a very fine sand, and it gets everywhere. We saw a few people wearing the sort of masks you see cycle couriers wearing. I saw one person who was wearing a mask, untinted skiing goggles, a hat and a scarf wrapped over everything. If you can imagine a Tusken Raider with an expensive jacket and a Nikon… I ended up improvising with one of my wife’s scarves. The dust is quite abrasive: I’ve noticed that Touch ID on my iPhone has stopped recognising my thumb print on my right hand, which has worn down to nothing. It’s probably not very good for you over the long term.

Kit: Wins and Fails

I brought two lenses: a 24-105L and my 100-400L. I also took my 1.4x extender, which I used for a couple of bird shots and the aard-animals (which I’ll come back to), which we couldn’t get close to. Having to focus manually with it is a pain in the arse. I could have left the walkabout lens at home. My wife’s OnePlus has a fantastic camera, and I was conscious of getting dust on the sensor with changing lenses. I’m going to get my camera body serviced at some point over the summer. I must have taken it in and out of my bag hundreds of times over the course of the holiday to try to minimise the dust exposure, but it’s got to have been affected by it.

One piece of kit that served me particularly well was a pair of noise cancelling Bose earphones which I’d researched, and bought in Duty Free on the way out – QuietComfort 20s. They were fantastic for the flights (particularly the small planes). The camps we stayed in were universally noisy at night – both wildlife and, at Kanana, some sort of generator or water heater. I’m a light sleeper so they were a godsend.

The biggest fail was inconsequential but amusing: my FitBit. With the shaking around on game drives I got credited with tens of thousands of steps that I didn’t take. On one record breaking day that I barely walked the length of myself I apparently clocked up 29k.

Masuwe Camp, Zimbabwe

We flew into Jo’burg with Virgin Atlantic, our first time on a 787. I was particularly taken with the button to tint the windows instead of having an old school sliding shutter. It also managed to land in ‘mist’ (which in this case is a euphemism for ‘fog’): we were told we were making a ‘special landing’ (that got our attention!), which required us to turn off all electronic equipment, including kit already in flight mode. The continuing mist then caused a 3 hour delay to our hop to Vic Falls airport in Zimbabwe. The queuing for visas there was farcical: you really need to know in advance what you want [we needed a Kaza visa for Zambia] and it was fairly apparent that most people didn’t.

Our guide picked us up and drove us to Masuwe Camp. We were the only guests there for the two nights we stayed, and it was fantastic. We dumped our bags and went straight out on a game drive, where we saw some elands (massive antelopes) which are a little uncommon, and then came back for dinner. I think the chef was bored: he really pushed the boat out.

Giant Elands

The reason the video above is quite grainy is because it was sunset, which is way past my long lens’ bedtime.

The camp has an artificial water hole which attracts a range of animals (mainly elephants and buffalo). It was good fun sitting up on the balcony watching the passing traffic.


View from the balcony at Masuwe – ISO 100; F9; 1/160 second

No cats though. We had a couple of raiding parties: vervets. Our first morning, they stole the jam from our table and, on the second, the toast. On the latter occasion I tried shooing the thing off with my napkin. It paused for a heartbeat and mentally went ‘yeah, right’, and ignored me, picking up the slices it had knocked onto the ground one at a time. I know from previous holidays that they’re dangerous, so I was pretty half-hearted about it.

We did wonder if they saved any of the jam from the morning before…

All of the camps we stayed in had a policy of accompanying the guests to their rooms after sundown. I initially thought this was a bit of theatre, up until the point on the first night when we couldn’t get back to our room because a buffalo decided to come and have a drink from the swimming pool.

On our first full day we had a trip to the falls (which were breathtaking), which we followed with a walk across the border for an hour in Zambia. One of the guys in work (Andre) has been to 120 countries, so I’m determined to clock up as many as we can! Anyway, apart from a fantastic view of the falls from a bridge on the other side of the border, it was a bit sketchy: a very hard sell from a couple of hawkers who walked with us for about 5 minutes. It was just the right side of threatening.

We rounded off our last full day in Zimbabwe with a pleasant enough – by which I mean boozy – boat trip on the Zambezi. Wildlife-wise it was a mix of hippos and birds.


Hippo – ISO 250; F5.6; 1/500 second
Cormorant, about to launch – ISO 800; F5.6; 1/400 second

A bee eater (not eating a bee, the shithead) – ISO 250; F5.6; 1/320 second

Chobe Elephant Lodge, Botswana

We had a short drive across the border, via Kasane airport, to our next lodge which was just outside the Chobe national park. The routine there was the same for the rest of the holiday: up before 6; breakfast at half past; out for the first drive; back for about 11:30; lunch at midday; break until 3 (because it’s hot enough even at this time of the year to reduce the animal activity); ‘high tea’, and then out for the second drive or boat trip.

Baboon kitten (possibly not the right term) – ISO 200; F5.6; 1/250 second

We had our first lion encounters in Chobe, which was fascinating. We also had an obscured view of them munching on something unlucky on our second day. Towards the end of our stay we had a pretty interesting boat trip, the highlight of which was watching a small herd of elephants crossing the Chobe river.

River crossing – ISO 200; F8; 1/400 second

Tidying up – ISO 200; F5.6; 1/160 second

This cracked us up: it’s a group of young elephants ‘head-waggling’: our guide said that when they are this young they have trouble controlling their heads because of how heavy they are. I’ve subsequently googled it and there may be other explanations…

…regardless, it reminded me of this:

Fast forward to about 1:16
Giraffe (partially deflated) – ISO 100; F5.6; 1/640 second
Buffalo: short-sighted, grumpy and a baked potato where their brain should be –
ISO 100; F5.6; 1/160 second

Okuti Camp, Botswana

After 3 nights in Chobe we had our first light aircraft transfer to the Delta. It was 55 minutes of sheer hell. My wife loved it. As a fairly nervous passenger at the best of times, I found that by the third one I’d got a bit more used to them, but I’ll never get to a point where I enjoy them.

Lilac crested roller – ISO 100; F5.6; 1/800 second

The Okuti camp was absolutely stunning. We ended up staying in a family unit – basically a permanent tent-like structure, with a balcony looking onto a lagoon. We’ve been lucky enough to stay at some pretty fancy places down the years, and Okuti was right up there with the best of them.

Hyena mother with pup – ISO 160; F8; 1/640 second
Now be honest Mum: did you actually wash your face this morning? ISO 160; F5.6; 1/1250 second

The staff were amazing. On our last night, we were surprised with a private dining experience – they had set up a table on one of the remote parts of the raised walkway around the camp, surrounded in candles – to celebrate a significant birthday my wife had a few months back. We hadn’t mentioned it, so it must have been passed on by our travel company. It was a really nice touch. So we ate our fantastic meal and drank champagne, listening to hippos grumbling and vaguely wondering if it was safe.


Side-striped jackal – ISO 200; F5.6; 1/400 second

Kanana Camp, Botswana

Our last two nights were in Kanana, via a 25 minute flight on a 5 seater Cessna. That suffered from the strangest turbulence I’ve ever encountered. Imagine sitting in an old mini, which is suspended – and swinging wildly from – a rope, but 4.5k feet in the air. Once again, my wife loved it.

The nutter.

Kanana is in a private concession. This was a new one on me: it means the guides are allowed to drive off-road. The animals are still completely free to wander: the only fences are there to try to keep the larger creatures out of the camp.

The already-impressive game moved up a notch at this place.

Hello, gorgeous – ISO 160; F5.6; 1/400 second
Say ‘ah’ –
ISO 160; F5.6; 1/640 second

This is one of my favourite photos from the trip:

Painted wolf (AKA African wild dog) –
ISO 500; F8; 1/800 second
Lovers’ tiff – ISO 160; F7.1; 1/500 second

The Aard-animals

I’m going to include a couple of shots that aren’t great, but which are of animals that are less common to see. First up we have the aardwolves, having an intimate moment in a not particularly intimate location (i.e., in plain sight):

Aardwolves – ISO 250; F9; 1/800 second (with extender)

I’d never heard of these before – I think they look a bit like a science project that went a bit wrong. We were quite a long way from the loving couple. With the 1.4x extender, I’ve found that adjusting the focus while holding the shutter release down (firing off about half a dozen shots) generally gives some reasonable results. It’s not pin-sharp, but it’s the best I got.

Next up we have an aardvark:

Aardvark – ISO 2500; F5.6; 1/10 second

The sun was going down when I took this so I really pushed the ISO. I jammed the camera into the arm rest on the jeep to keep it steady for the slow shutter. It’s ok, and about as good as I could have hoped for. They are odd looking spuds, got to be said.

…And home again

The trip home was a slog. A 25 minute flight – which my wife sat in the co-pilot’s seat for – on a light aircraft, which took us to Maun. From there we got on a reassuringly large SA Airways flight back to Jo’burg. That flight was notable for having the most bizarre food we’ve had since our fruit salad with prawns on an internal flight in Vietnam 10 years ago. I had cold meatballs, served with what appeared to be minced up pasta mixed with coleslaw.

Yum.

The flight from Jo’burg was long but uneventful. And so we are back in the startlingly grey Blighty, fatter than when we left, and talking about nothing except the wildlife, the hospitality and the downright fabulousness of Botswana.

I’ll add a few more pics and videos when I get round to it.

Sky Broadband, YouTube Restricted by Network Administrator and Other Woes

TL;DR: if you’re a Sky customer and YouTube suddenly seems a bit broken, have a look at a service called ‘Broadband Shield’. Read about what it’s doing before you turn it off: you may actually want to live with it.

During the week, I started noticing something weird was happening with the DNS on my home network. I don’t have anything vastly complicated set up, but I use pfSense to apply rules to route traffic between three physically separate networks. I’ve had a mess around with DNS configuration before, so that was my first port of call. I tried changing over from Google to CloudFlare to see if that helped, in a just-home-from-work-let’s-poke-a-stick-at-it sort of way. It didn’t. I was able to get access to various sites in the .com domain – and we’re talking imap.google.com, so not exactly off the beaten track – for a while, and then all of a sudden, the names would stop resolving. Oddly enough, I seemed to be having the same problems with my VPN, which I thought offloaded DNS. I didn’t test this thoroughly though.

The real clue came with YouTube, where I was noticing that some videos and all comments were being blocked, and some rendering problems in the app view layout – stuff where there should have been content was blank. Initially I thought this was because Google was delivering content from different domains, and my DNS woes were continuing. Looking at the settings for the YouTube app, the switch for ‘restricted mode’ was greyed out with some text explaining that it had been enabled by the network administrator. Up until this point, I’d have assumed this was me :).

A little bit of googling later to see what sort of parental controls Sky were offering me landed me at the Broadband Shield site. I turned it off, and suddenly all of the name resolution weirdness disappeared, and the YouTube comments were back.

I appreciate the intent with the Shield service but I’d appreciate it a lot more if Sky had told me that they were turning it on, or changing it in a way that would apply a pretty broken policy to name resolution.

Parsing FIDO Raw Messages

I’ve spent the last few weeks working on iOS app to use a Feitian BLE Multipass token. When I get to the final version of that I’ll do a separate posting but parsing the raw messages to and from the device turned out to be pretty challenging. Unfortunately, if you send something that doesn’t conform to the required format, rather than getting an error back, you get no response at all. This makes debugging [particularly at the start, when I really didn’t know what I was doing] tricky.

While the standards for both the FIDO BlueTooth spec and the raw message format are both well written, there are a few bits that aren’t immediately clear, and that I couldn’t find documented anywhere.

The Feitian device enforces a maximum fragment size of 20 bytes. Any arithmetic I use in the rest of this write-up will assume this, but that will vary from one device to another. Also, I will tend to use the actual number of hex characters transmitted. As the payloads are double byte, this will mean that a decimal value will be derived by converting a hex value to decimal, and then doubling it.

Sending An Enrolment Command

The first fragment you send looks like this:   

The FIDO command prefix has the value 830049. The 83 indicates a message, the 00 is a blank high data length, and 49 is the length in hex, which equates to 73 in decimal, 146 characters. This is derived from adding together the APDU command prefix [14 characters], the concatenated challenge and application parameters [128], and the a final 4 characters, all zeroes, which are the APDU Le values. 

The APDU command – the example I’m using is enrolment – has the value 00010000000040. As per section 3.1 of the raw format spec, that’s a preceding 00, then the enrolment command of 01, then a bunch of blank parameters, and ultimately the 40, which equates to the 64 bytes for the combined length of the challenge and application parameters.

For each of the subsequent chunks, you have a payload [in the Feitian’s case] of 19 double bytes, plus one more byte for the order. The last message includes the 4 bytes for the Le values.

Parsing the Response

The response is a bit trickier. First, the device may respond with a FIDO keep alive command, which is 82000101. So before I start concatenating the full response, I check that the individual chunk value doesn’t equal this. Just a quick detour into the implementation: the BlueTooth spec says that the values you get back from the token will be Big Endian double bytes. I couldn’t find a nice way of processing these using an NSUTF value, so I just convert them to text and parse out the angle brackets and spaces.

On to the processing. The first six characters I get are 830259. Per the spec, 83 is playing back the original command. 259 in hex means that the total length of the response will be 1202 characters. That’s going to vary: both the attestation certificate and the signature are variable length. For my implementation, I calculate a running total, so that I know when the final message has been sent.

So, there is no APDU header at all in the response. After the 6 character FIDO header, you get straight into the standard payload as per the spec. You have a legacy 05, then 130 characters for the public key, then a key handle length. For my device, the value is 60, which translates [96 in decimal x 2] to 192 characters. 

The next part took quite a bit of digging, which is figuring out the length of the attestation certificate. The certificate starts with the following: 30820168. While my read of DER encoding of ASN.1 [ugh!] is that the length specification can vary, for me, that 0168 is the length in hex, equating to 360 bytes. Add back in 4 bytes to include the header [30820168], that gives me an attestation cert length of 728 characters. 

What remains is 144 characters. The last 4 are 9000, which per the raw message spec is the SW_NO_ERROR value. 

And that’s it. 6 weeks of trial and error in about 700 words.

Hue, Alexa and “A few things share that name”

Edit 09/10: what I described below didn’t work: Alexa adds in all of the copies of the scenes cyclically, presumably every day. What I ended up having to do was:
* Fire up the app, go in to the room settings and delete all of the scenes except ‘bright’. This may be a non-starter for some people straight away.
* Change room names: this is fairly tedious but it was the only way I could think of getting it to work. I had “X’s bedroom” and “X’s bedroom light”. This seems to be enough to trip up the commands. As you need to retain the room definition, I simply made it “less intersecting” with the light name, by renaming it to “X’s room”.
* Final gotcha. Do a ‘discover’ in the Alexa app. All of the scene definitions are marked offline. I had to delete them again, then do a rescan [enough to reinsert them before deleting the light-scene association in the app] and they were gone.

This is so torturous I’m fairly sure I’ve missed something obvious. If I figure it out, I’ll update this posting. If it breaks overnight because Alexa runs some weird batch job *again* I’m going to delete the article and pretend I never started with this :).

==== Original post ====

This has been really bugging me over the last few months. Voice commands to control our Hue lights stopped working with the ‘a few things share that name’ response.

I am pretty sure it was something that Amazon introduced: what breaks the voice commands is that it treats both rooms and scenes as separate targets for control. I deleted the room references in the devices list and the scenes – 12 per room, which is quite tedious – and the ‘off’ and ‘on’ controls have started working again.

There are a couple of gotchas: the first is that the Alexa web interface – which I used for all of the changes – offers a ‘forget all’ option at the bottom of all of the Hue related pages. This deletes everything, not just the scene or room that you happen to be editing. The second is that a rescan adds all of the scenes back in, which is quite annoying.

So what Alexa seems to be doing is getting a list of resources from the bridge, and then taking copies of them locally to act as command targets. Some of the scene names are pretty convoluted, and by virtue of the fact that the commands you want to use – ‘turn off x light’ – contains a substring of some of the constructed scene names, the language processing won’t let you use it.

It’s not the smartest move to do the Alexa integration this way: just blindly adding the default scenes is almost guaranteed to break the functionality you want to use.

Anyway, deleting the stuff you don’t want from the Alexa UI has no impact on the resources on the bridge.

Using Sunset to adjust Philips Hue Sensor On/Off Times

I’ve been meaning to do this for ages, and it turned out to be a bit easier than I thought. The Python I’m using is a bit rough and ready – rather than the 8 separate API calls to PUT the date changes back [4 rules for each sensor], I could do this with one API call, based on the single data structure for all of the rules. It doesn’t really matter that much.

I haven’t done anything for sunrise processing, which fits our usage patterns with the sensors.

Here’s the script, which I’m calling from cron, once a day, which is a bit of overkill. I could probably do it weekly:

#!/usr/bin/env python3

import requests
import json
import time
from datetime import datetime, timedelta

fudgeFactorMins = -30
morningOffTime = "T08:00:00"

The fudgeFactorMins variable is an offset for the actual sunset: I eventually subtract this from the sunset date. The rule numbers are not going to be nailed on, but they do appear to be contiguous for each sensor, in groups of 4:

# Format: "T20:00:00/T08:00:00"

# 8am / 8pm: day-on
bathroomDayOnRuleURL = "http://yourIP/api/yourKey/rules/1"
# 8am / 8pm: day-dark-on
bathroomDayDarkOnRuleURL = "http://yourIP/api/yourKey/rules/2"
# 8pm / 8am: night-on
bathroomNightOnRuleURL = "http://yourIP/api/yourKey/rules/3"
# 8pm / 8am: night-dark-on
bathroomNightDarkOnRuleURL = "http://10.40.0.3/yourIP/api/yourKey/rules/4"

# 8am / 8pdm: day-on
livingroomDayOnRuleURL = "http://yourIP/api/yourKey/rules/9"
# 8am / 8pm: day-dark-on
livingroomDayDarkOnRuleURL = "http://yourIP/api/yourKey/rules/10"
# 8pm / 8am: night-on
livingroomNightOnRuleURL = "http://yourIP/api/yourKey/rules/11"
# 8pm / 8am: night-dark-on
livingroomNightDarkOnRuleURL = "http://yourIP/api/yourKey/rules/12"

This is a bit messy but…

allUrls = [bathroomDayOnRuleURL,bathroomDayDarkOnRuleURL,bathroomNightOnRuleURL,bathroomNightDarkOnRuleURL,li
vingroomDayOnRuleURL, livingroomDayDarkOnRuleURL, livingroomNightOnRuleURL, livingroomNightDarkOnRuleURL]

The sunsetAPIurl refers to a free API. I had a look at one implementation on StackOverflow which calculates locally. This endpoint is returning results within a few mins of the app on my phone, which is certainly good enough.

One slight nuisance is that I need to adjust for British SummerTime. What I’m doing for now is using Daylight Saving as the Python datetime library gives you it for free. It’s going to ‘wrong’ for the week or so when DST and BST are out of synch at the start and end of the summer, but I can live with that for now:

sunsetAPIurl = "https://api.sunrise-sunset.org/json?lat=yourLat8&lng=-yourLong"

def getSunset(sunsetAPIurl):
   r = requests.get(sunsetAPIurl)
   jsonData = r.json()
   # date format is 8:08:18 PM
   dateFromJson = datetime.strptime(jsonData["results"]["sunset"], '%I:%M:%S %p')
   if is_dst():
     adjustedSunset = dateFromJson + timedelta(hours=1)
     return adjustedSunset
   else:
     return dateFromJson

def is_dst( ):
    return bool(time.localtime( ).tm_isdst)

So another quick adjustment to reformat to the requirements of the Hue endpoint date handling, after processing the fudge factor:

def adjustSunsetToString(sunset, fudgeFactorMins):
  fudgeAdjusted = sunset + timedelta(minutes=fudgeFactorMins)
  return fudgeAdjusted.strftime('T%H:%M:%S')

def hitEndpoint(allUrls, dayOnString, nightOnString):
  for oneUrl in allUrls:
    r = requests.get(oneUrl)
    jsonData = r.json()
    currentDate = jsonData["conditions"][0]["value"]
    #print("currentDate: " + currentDate)
    ruleName = jsonData["name"]
    #print("rulename: " + ruleName)

The dates that I push back into the JSON need to conditionally flick around [earliest / latest or vice versa], which I do based on the substring search for ‘day’ on the rule name:

 
    if "day" in ruleName:
      jsonData["conditions"][0]["value"] = dayOnString
    else:
      jsonData["conditions"][0]["value"] = nightOnString
    newJsonPayload = {"conditions": jsonData["conditions"], "actions": jsonData["actions"]}
    r = requests.put(oneUrl, json = newJsonPayload)
    #print("response: " + r.text)


sunset = getSunset(sunsetAPIurl)
adjStrDate = adjustSunsetToString(sunset, fudgeFactorMins)

dayOnString = morningOffTime + "/" + adjStrDate
nightOnString = adjStrDate + "/" +  morningOffTime

hitEndpoint(allUrls, dayOnString, nightOnString)

 

Deleting My Apps From The App Store…

Five and a bit years after I released my first app, WeighMe, I’ve just deleted it and Pin Your Pics from the App Store. Here were the total downloads:

Total App Downloads

The reason I’ve zapped them is simple: it doesn’t make sense to continue to invest serious amounts of time in Objective C, in [for Pin Your Pics in particular] what developed into pretty large and complicated codebases. Apple made an announcement quite recently that support for iPhone X screen dimensions is about to become a mandatory requirement, which was going to be quite a bit of work for me.

But the more immediate death knell for Pin Your Pics came a few weeks ago when Google announced a change to their Maps API. Up until this month you could get an API key, and it would just stop working above a fairly generous threshold. Now you have to sign up with your card details. While my app usage is unlikely to trouble the new limit, it’s a chance I’m not prepared to take.

I am a bit gutted that, when Google cut over the API, the app is going to break quite unceremoniously, which is a bit rubbish for people using it. But I hadn’t updated it in ages and it was starting to get fairly unstable anyway.

I still code up the odd utility in Objective C but I’m not going to renew my developer subscription when it expires this year: I really can’t see myself publishing any more apps.

Some interesting numbers buried in the 5k download total. More than half were in China. I have no idea why. Also, that spike last September was weird: 1.9k downloads that month alone. I did absolutely no marketing for either of the apps. Finally, to my lone ‘customers’ in each of Uzbekistan and Kazakstan, thank you for using my apps, whoever you are :).

Fitting a Mastery Bridge to an American Pro Jaguar

I bought a Mastery M1 to replace the stock Fender bridge on my 2017 Jaguar during the week. I asked at a store to double check that it was compatible – I wasn’t sure if I needed the kit, including the thimbles – and was told it was.

I then found that the posts on the Mastery were too wide, by about a millimetre or so.

I searched everywhere online to try to figure out what I needed to do to fit the thing. I was hoping that it would be something that I could do myself, but I really didn’t want to tackle anything that was irreversible.

I couldn’t find anything specific to the American Pro, which is why I’m writing this up, on the off chance that Google lands someone else here who is thinking of doing the same thing.

Long and short of it, it’s a doddle. The plastic mountings [thimbles?] that the stock bridge fits into are less than a centimetre deep. I very carefully levered them out of the metal fittings they are inserted into using one of the Allen keys that came with the Mastery. As I couldn’t tell the dimensions of them before I started, I initially thought I’d have to take them out and replace them with the Mastery thimbles.

You don’t need the Mastery thimbles.The M1 fits perfectly on its own.

Here’s a quick snap showing the little mounting that I removed:

American Pro Jag with Mastery M1 Bridge

 

Philips’ Hue Sensor Automation

I wrote about my first pass at the Philips’ Hue API to customise the motion sensor functionality back in December. At the time, I tested out my approach to force a third time slot [use of a nightlight setting for part of the the night] using a simple mobile app in Objective C. The approach isn’t that fancy: it’s basically 3 API PUT calls: two to rules, and then a third to a resourcelink all basically doing the same thing: inverting references to scenes [one for full brightness, and the other for the nightlight setting].

At the time I thought it would be handy to use a Raspberry Pi using cron jobs to toggle it off and on, and the long and short of it, that’s what I’ve gone with. It’s a simple Python script [using the Requests module, which is great, to make the API calls], and it’s working really well so far.

A couple of observations. First, I found an article on the Hue discussion forum – which I only found when I got a weird error and which, unfortunately I can’t find any more – that has what’s probably a more purist way of using the API to create extra slots. While it’s smarter than what I’m doing, unfortunately [and the author of the post does point this out] it has the effect of stopping the mobile app from working to set the sensor.

Secondly, my approach is pretty brittle. Between writing the app and implementing the Python script the state had changed in the bridge: there was a new scene [not one we added – at least intentionally] which was causing the API calls to fail.

Currently, my script is doing exactly what my mobile app did, which is creating the PUT payload for the API calls from files, and ‘hoping’ that they work. What the Philips’ mobile app does is to GET the various API resources and then PUT them back. I’ll do this when the current implementation breaks as it’s more trouble than it’s worth for now.

I was telling someone at work [a proper developer] about my results with proxying via ZAP, which I had to revisit to figure out why my original implementation had stopped working, and he couldn’t believe the fact that the app is making around 55 API calls to effect a change in the sensor setup. Based on the diffs I looked at, It seems to pretty blindly do the GETting and PUTting where no changes have been made.

I managed to completely corrupt the setup on the bridge by playing the ‘I wonder what will happen if I do this?’ game: I deleted the scene that was breaking my API calls. I ended up having to do a factory reset – about a five minute job for me, but worth bearing in mind if you are playing with this stuff and have a more sophisticated configuration.