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.

Hello Laos, Cheerio Aperture

We got back from our latest long haul trip at the end of January. I normally try to write up our interesting trips as quickly as I can while I can still remember everything, but I’ve been migrating off my old Mac Pro – or more specifically, Aperture – which has turned into a pretty torturous affair. As it’s also something that has a direct bearing on the photos I’ll be embedding in this post, I’ll make a few comments on it. With the demise of Aperture landing at some point, I imagine there are a lot of people planning a similar move.

The long and short of it is that you have a few choices with your library under management with a view to moving, and – beyond the obvious, like organising your source files in a sensible directory structure – they all revolve around what to do with your edited files. You can either save them as separate duplicates files into the same library and live with the repeats, you can store them separately and live with the disconnect, or you can throw them away. After a lot of messing around I chose the final option.

This sounds draconian, but most of the changes I was making in Aperture were pretty minor – just topping and tailing exposure settings. There are a couple of exceptions to that, and the first is portraiture: I’ve tended to put a lot more effort into those. However they tend to be one-offs: I find I work on them at the time, send them to people, and then don’t really think about them again. I still have all of my original Aperture files backed up on a cloud service, so I have a few months to make up my mind as to whether or not I care; for now, I don’t think I do. The other exception is HDR but the Nikor plugin for Aperture that I was using saved the resulting merged file back as a Tiff, so I’ve got all of those.

If you are planning on a more sophisticated approach, like import tools, don’t bet the farm on it. I couldn’t get LightRoom’s offering to work.

It appears that I’m not alone in finding the subscription model that Adobe is applying to Lightroom unpalatable, and paying a perpetual license for the never-to-be-updated-again version amounts to swapping one timebomb for another, so I’m trying a couple of the alternatives that have sprouted up. The one I like best so far is On1, which has much more sophisticated editing features than Aperture [something of a mixed blessing], and won’t break the bank.

One final comment before I get onto the trip. I made a mistake over the 8 year period that I was running Aperture on the same machine. As I ran out of space I added a couple of SSDs as I went along, and decisions I made that seemed like a good idea at the time – in terms of splitting up my photos – were messy to retrace years after the fact. If it happens again, I’ll deposit READMEs for myself as a memory aid.

Anyway, on with the trip. The numbers of photos we took were well down by recent holidays’ standards: I took less than 400 and my wife took 275. There were a couple of reasons. First and foremost, it’s a low key destination for wildlife. I sweated blood over what lenses to take to Cambodia a couple of years ago, and ended lugging around everything, including my 100-400, which I used precisely never. So this time I took a more conservative approach: I packed my wide lens, my 24-105 and 100mm macro. I forgot my dust blower, which made me wary of getting dust on the sensor [a bloody nuisance to clone out after the fact] so, barring a couple of half-hearted, half-drunk HDR sessions with 16-35, I kept my walkabout pretty much nailed on the whole time we were there. That meant I could take a much smaller bag – annoyingly, still too big to put under the seat in front of me on the Thai Airlines flight. It was an A380, and the cabin service was pretty decent [putting Air France to shame on our last long haul with them], but the seats had an odd configuration. There was a metal container along the side of one of the legs in front which, never mind my bag, meant that we couldn’t put our legs out straight for the flight. Bearing in mind that we’re both at the smurf end of the height distribution, it was pretty uncomfortable. I’ve a feeling that the metal boxes may have contained life jackets, so I guess we can file those under “necessary compromises”. So I ended up doing what I hate: putting my camera bag in the overhead storage and then having kittens every time someone goes near it.

The second reason for the low exposure count was that I got a camcorder for Christmas. I’m not going to post the results here because, frankly, I’m rubbish.

We flew in via Bangkok. The only point worth passing comment on is the fact that Bangkok airport is furiously expensive. Our layover was about 4 hours so once we’d figured out the puzzling procedure for transferring without a boarding card, we could relax and try to stay awake. Then we had a couple of hours on a twin prop plane into Luang Prabang airport, which was painful getting out of. There was an incomprehensible – well, with jet lag descending – queuing system for the visas, which flummoxed everyone, but which was endured in a good humoured manner by everyone. The patience started to evaporate when we spent a good half hour at the baggage reclaim, getting dizzy watching the same bags going round, and wondering why there was a queue forming at a desk next to it. We eventually found out that the plane was unburdened by luggage for all the passengers who had transited via Bangkok. That was about half the plane we reckoned: you have to admire the even-handedness of it, if nothing else. One American lady was threatening litigation. The bags duly appeared at the hotel the same evening, so I doubt she’d have had a chance to dispatch her lawyer.

Our first pit stop was Le Sen Boutique in Luang Prabang, which we both really enjoyed. The room had an unusual layout, with an absolutely enormous bed right next to the bath. It also had two showers, which I think was a first for us, solving a problem which we didn’t know we had: who showers first. I think it also had the best breakfasts of the trip. Luang Prabang [I have to almost physically restrain myself from adding ‘Kipperbang‘] was a mixed bag. While it’s touristy, we had some absolutely cracking meals there.

On the whole, the food we had throughout the holiday was fantastic. Having been to the 3 countries comprising former French Indochina, based on our admittedly limited experience, I think I’d rate the food in Laos the best. It’s a combination of unusual flavours, and very heavy uses of herbs and spices. My predominant recollection of the food in Cambodia was that it tended to be quite sweet. The Lao food is closer to Vietnamese in style, but is very distinctive in its own right.

We ate in a place called the Coconut Garden on the first night [a bit simpler than subsequent nights but nice], then had a fairly fancy tasting menu at the 3 Nagas, and finishing in Tamarind on our last night. I’d rate Tamarind as one of the food highlights of the holiday.

We had an early start on our first full morning with alms-giving. Someone at work had done this a couple of years ago and said it was packed. We were the only tourists at the spot we were taken to, which was a little off the beaten track in a residential part of town. I have to say I had mixed feeling about participating. It felt like a bit of an intrusion, and it’s part of a faith that I know practically nothing about.

Glass Buddha

We spent rest of the morning walking around the town, the highlight of which was the local market [distinct from the night market]. Among the delicacies on sale were barbecued rats and squirrels. They look like any other cooked meat up to the point where you get to the head and feet, still attached, and with their teeth queuing up to get out of their mouths. We passed: having been hospitalised on our last trip to SE Asia, we tend to be very conservative with the street food options.

That afternoon we drove up to the Kuang Si waterfall. It was quite busy, but it was a pleasant enough walk up there, and the falls themselves were spectacular. I enjoyed watching a bloke flying what seemed like a very fancy drone. I have to admit they are on a [very] long list of toys I’d quite like. But as my wife will attest to, I have  enough expensive hobbies to be getting on with, and there is a huge potential for expensive mistakes with them. They must make packing for holidays interesting. I could see myself with a choice between the drone and clothes.

Kuang Si

We had the next day to ourselves, and had a long walk from the hotel to the far end of town, which was a nice way of spending our last day while still wrestling with the jet lag.

Temple in Luang Prabang

The next day we flew to Vientiane, which we both really liked. My wife said that she could imagine herself living there. She didn’t say whether or not I’d be in tow her but I remain hopeful. But, as we told ourselves, it was the middle of winter. It would be a very different proposition when it’s 40C+ and in the middle of the rainy season. There was a really relaxed feel to the place, lots of interesting shops and big wide boulevards. I was tempted to buy an old, ornate opium pipe in an antique shop for all of about 10 seconds, up to the point when I realised that it might turn into an interesting discussion at customs on the way home. We didn’t have any excursions planned for our first day in the capital, so it was nice pootling around and taking in the sights and sounds.

Vientiane

The room we had in the Ansara Hotel was vast. It had its own office area, just in case we were missing work, and had access onto a large terrace overlooking the pool. I was quite taken with the little laptop in the office which was running Ubuntu in some sort of kiosk mode, something I’d never come across before. I had a bit of a poke around: it seemed to create a new user every time it rebooted, which was quite an interesting approach to privacy. A point lost on whoever used the machine before me [without rebooting] and who failed to clear their cache: nothing dodgy, just really careless.

Anyway, back to South East Asia…

Vientiane HDR

We had what my wife rated as her standout meal on our last night, in a spot called the Lao Kitchen. She was amused to overhear a scrotal old duffer [he was English] telling his other half at the table next to us, “that’ll be on bloody Instagram in a bloody minute”, when my wife took a picture of her food – for private consideration, I might add. Part of me can’t wait to get to that age where all sense of discretion and your ability to judge how loudly you’re talking simply sail off into the sunset. Off to meet your long-departed moderate political views, I might add.

I won’t think of it as “going on holiday” any more, but rather “going abroad to complain about all the bloody foreign stuff” :).

Our second and final day in Vientiane was taken up with a tour of some temples. Interesting enough, but wasted on me. From there, we started a long trip south on Route 13, which we’d continue for the rest of the holiday. Our first stop was at a place called the Spring River Resort in Hin Boun. It was a stunning location. The room itself was a little on the basic side [no air con; electricity off for the early part of the day], but it overlooked a river with steep limestone formations looming over the other bank. The jagged karsts dominated the views for much of the rest of the journey.

Spring River Resort

Despite having relatively basic facilities, the network at the Resort was fantastic – something that we found repeated throughout the country. One more quick aside on the technology front, which really made me giggle: my iPhone wasn’t exactly tying itself down too much with the location for the weather:

The weather in the general vicinity of…

For what it’s worth, I’ve played around with the Google API that takes GPS coordinates and turns it into an address. This looks like a backing off of accuracy, based on address availability, taken to an extreme level.

It was a shame that we only had one night at the Resort because we really enjoyed it, but the main purpose of the stay was to break the journey so we could do a tour of the Kong Lor cave. It was really good fun: unlike our crystal maiden experience, we had full access to cameras, but I bottled out and left my SLR at home. The cave itself is huge [so even the flash would have been a waste most of the time] with most of the trip covered in a motor boat going at full tilt. The site could do with some more development: everywhere we pointed the head- and hand torches there were interesting rock formations, but we spent the majority of the hour or more we were in the cave in the dark, hoping that the guy driving the boat knew where he was going, and when to slow down.

Our next stop was in a town called Thakhek, which had a wild west vibe, and had what was probably the worst of the hotels we stayed in – the Inthira. It wasn’t terrible, it was just that the staff were almost universally miserable, and the food was a bit pants. Still, there was a decent little bar in the square across the road, where the beer was cheap and ice cold. Slightly incongruously, we had fantastic pizza on our last night there at a spot called Patalai.

Thakhek

We had one full day of sightseeing when we were in Thakhek, which started around a village called Ban Nakhang Xang in the morning. It was the closest that we came to something going wrong for the entire trip – other than the errant luggage – when a local guide failed to materialise for the first half hour. The walk started at the village, and quickly became quite steep via an overgrown path, at which point the shorts and sandals were starting to seem like a bad idea. After passing by a lake called Nong Thao, which was stunning, we ended up at our second cave, called Nong Paseum. It was occasionally a bit hairy clambering up and down over boulders, but interesting enough. Our final underground adventure was that afternoon, with a trip to the “Buddha Cave” at Nong Pa Fa. It was spectacular, but as an active Buddhist religious site, no cameras were allowed.

The last leg of the holiday started with another long drive down Route 13 to Champasak. We were staying at a hotel called The River Resort. The staff were fantastic, but it was very pricey. We ended up spending more in our 3 nights there than we did during the rest of the holiday combined. It has to be said it was a spectacular location, right on the bank of the Mekong.

Next up on the itinerary was the “4,000 island tour”. My wife was starting to feel the pace by this stage so decided to sit it out. A white lie that she wasn’t feeling well [rather than just saying she needed an idle day by the pool] started to take on a life of its own when our guide insisted on telling the every staff member at the hotel to look after her. Meanwhile I was sheepishly saying that, really, she wasn’t that ill, all the while receiving withering glances for being a heartless bastard.

It was a physically demanding day, the best parts of which were the boat trips to and from the island of Don Khone. I could have taken or left the island itself: it was OK, but not really enough to warrant the long journey at that stage of the trip. Part of the day out involved transferring onto yet another boat to go and have a look at some fresh water dolphins. “Boat” is an evocative word, all sleek lines and sunglasses. By contrast, ours was a bloody wreck. I could see the water through a joint in the wood at the pointy end where I really don’t think you should have been able to. It was also incredibly uncomfortable, sitting on a slat a few inches high. We did see the dolphins but by that stage my back was so sore I could barely have mustered interest if they were doing somersaults, rather than just breaching the water every now and then.

Or as dolphins probably call it, “breathing”.

Mekong

Lippi Falls

Our last outing was a look around the Watt Phou temple complex. This was a highlight of the trip. It was scorching though: the further south we travelled throughout the fortnight, the hotter it was getting. There is a slog up some steep steps to the temple so it was tough going in, what I reckon was mid-30s Celcius the day we went up there.

Watt Phou

Watt Phou

We weren’t able to stay in the country as long as we liked, because all of the hotels that made sense for our itinerary were full at the end of the second week. So, we had a long drive starting in the early afternoon of the Thursday, from Champasak across the Thai border to a regional airport called Ubon Ratchathani. One notable experience on the drive: we started it on the right hand side of the road and then, after crossing the border on foot, we got back into the car and continued on the left. It was a first for us. Contrary to what I guessed at the time, it’s actually not that unusual. There are vast swathes of former British empire influenced countries were you can do it.

When we got to the airport, we’d been misled by a couple of little details with the online check-in process that you normally take for granted: the time and the flight number, neither of which were on the departure board. Not a great leap of faith in the end – we worked out that ours was a flight with the same company going 10 minutes earlier or later – but it got our attention for a while. One slight nuisance was that we had to get our luggage at Bangkok. We were debating whether or not we would have to go all the way out through customs and passport control, and whether we’d have enough time. We did, and we did.

So, that was our couple of weeks. We’ve talked about going to Laos off and on since we went to Vietnam back in 2008. It’s hard to put our feelings about the place into context without sounding like we’re damning it with faint praise, but it’s lower key than some of the other places we’ve visited in Asia. Cambodia left more of a mark on us, but that’s principally to do with visiting places which remind you of how utterly traumatic its recent history has been. And we did get spectacularly ill in Phnom Penh, which we won’t forget in a hurry. Rather than raving about it since we got home, we’ve been a bit more measured in our praise. But there was plenty to see, the food was great and people were really friendly. Well worth the trip.