There once was a product called Hannover…


Once upon a time – think 2006’ish – a complete revamp of a product was unveiled. The revamp went under the codename Hannover after the name of the city it was unveiled in. The revamp was to blow competition away and make the supplier of the product rule to World with the new product platform, new technologies and all the amazing stuff the client would be able to do. And it was amazing. It was like magic and provided access to new and amazing features and exposed great API’s that allowed developers to build sweet apps to bridge the gap between the proprietary world of yesteryear and the new internet era. It was built on a proven open source source platform and built using a proven industry standard programming language that many developers knew. It could be said that the language was the Lingua Franca of its time. To make it even better the client would be backwards compatible and run all the apps of its predecessors – like all the way back to the very first version of the product from the good ol’ DOS days. In many ways it was almost too good to be true.

It did however also not quite turn out the way the supplier had hoped. There was a problem with all this goodness. Not in the product. Not in the ambitions. Not in the chosen platform. In many respects it was a good idea, a good launch and the product delivered in most – if not all – of the areas it had promised new and amazing solutions for.

The problem was in the application developer support. They failed the product. Or maybe more to the point – the supplier failed the developers.

For the last 5-10 years nothing much had happened on the platform. Sure the platform had adopted JavaScript and Java and sure it had brought incremental improvements to the appdev experience. New feature here. A new simply action there. But nothing massive. But now the supplied threw this completely new way of developing apps on the market. The change was so massive and all the supplier would talk about was all these new capabilities – why wouldn’t they? Problem was that they had lulled developers to sleep with histories of declarative programming and how visual programming and laying out elements on screen was enough. One client to rule to them all. Simple actions and formulas to solve complex issues. But then all of a sudden developers was expected – from one day to the next – to grasp component development (called JSR 168 portlets at the time), data coming from different backend sources, UI threads, async programming, regex’es and low level widget development.

I’ll go out on a limb and state that the product was a failure. Sure customers migrated to the new client but many hesitantly. And it took a long time. Many never reaped any of the benefits of the new platform and ended up jumping ship.

Some developers did make the jump however as they were real developers. But many did not. It sounded too complex to them and it was. It didn’t align with the World they knew. They were business peoples trained to be developers – not developers by trade which was really a requirement. They chose to ignore the revamped product and all the features it brought. So all the good effort, energy, time and money put into product fell by the wayside. Sure it was used by some (including yours truly) but for many it was never adopted. So sad…

But why is this important and why am I writing it now?

Well to be completely honest it’s just a brain dump of thoughts. I find it interesting as time passes how often I see the same pattern reappear. Different products, different ways they try to reinvest themself and different results. In my opinion completely reinventing the way things are done in a product without making absolutely sure you either address the new message to the right audience or make sure the story is complete when told is due to fail. Of course some products are better than others and some suppliers are better at listening than others. But it’s interesting to watch.

But boy that Hannover product could have ruled the World if the supplier had been better at preparing developers beforehand and making sure they got on board.


That moment when grown men start crying…

OK I admit it. I cried. A little… So there are many emotional moments in a life but seeing the succesful launch of the SpaceX Falcon Heavy is one of those. I cannot not be impressed of the work it must have taken to a) design the thing, b) build the thing, c) launch the thing and d) bring the freaking boosters back to Earth. Oh and the secret e) the social media coverage and small touches from the Tesla Roaster onboard, Space Man,  the “Don’t Panic” text on the screen, the plaque of names and finally but not least Life on Mars by David Bowie playing alongside. Wow! Just wow!

I highly recommend watching the video of the launch with the intro or if you’re not quite to it the actual launch from T-10 seconds below it.

Salesforce Release Notes

So I’m reading through the Salesforce Spring 18 release notes for a customer project starting later this week for specifics on changes related to GDPR. So happy for searching as the release notes are a wopping 459 pages. What! Seriously? Oh yes…

The way I tend to go through the release notes is to get the PDF version as I find it easier to skim and search through. The release notes are also available in HTML which can be good if you know you’re only looking for say Lightning related changes or AppDev related changes.

Only other piece of advise – make sure you’re sitting comfortably and have coffee at the ready!

Salesforce Spring 18 release notes (PDF)
Salesforce Spring 18 release notes (HTML)

Hello WordPress World!

So I’ve finally made the move from the old trusted blogging platform I’ve been using since 2004 (!!) to So no more hosting myself but hosting and paying a provider in the Cloud ( I’ve never really used WordPress besides looking looking a bit so this should be a fun adventure.

The conversion was done by yours truly using a script I wrote to convert from the old proprietary XML format to the WordPress format. The script is written in Typescript and can be found on Github if anyone is interested. To start out with the script would convert both posts, comments, tags, images and files but I was finding the import of images pretty unstable so for the final import I scrapped that part and just uploaded all images and files manually.

While I’ve been testing the support from has been very cool and very helpful. Thank you.

Final stats for the conversion was as follows:
Posts: 1633
Comments: 2542
Files: 142
Images: 402

All this since 2004 with my first post ever on adding additional tuners into my MythTV box to my last on the Pebble platform in 2018 on unsigned integers on Arduino.

Thank you Pebble. I’ll soon be putting the old server to rest in the recycle bin on some old VMWare server somewhere. We had fun. You’ve followed along for the last 14 years – let’s see what the future will bring.

Note to self – subtracting unsigned integers

I was having a small Arduino problem this weekend involving counters so had to do some research on subtracting unsigned integers from one another in the context of counter rollover. Interesting solution to that problem using modulus UINT_MAX+1. Thank you to this answer on (Is unsigned integer subtraction defined behavior?). Below is my test code.

#include <stdio.h>

unsigned char counter = 0;
unsigned char previousCounter = 0;
unsigned int interval=47;

int main () {
   for (int x=0; x= interval) { // check for rollover
         printf("Reached interval at %d (%d), %d n",
            currentCounter, previousCounter, (unsigned char)(currentCounter - previousCounter));
         previousCounter = currentCounter;

Solving my Sonos morning alarm problem

I’ve jumped on the Sonos bandwagon a while back and I have a couple of Sonos players around the house. One in the bathroom, one in the kitchen, in the living room etc. I’ve been using them with alarms in the morning (weekdays only) so that the bathroom one tuned in to local radio (streamed of course) at 5.30am, the kitchen one joined in at 6am and then the upstairs one at 6.30am when it’s time to wake the kids. The problem with this setup is that Sonos does not offer a way to let the players join into the same group meaning that eventually / sometimes they will be slightly apart in the streaming of the audio which is really annoying. I’ve been looking for a solution for a while but didn’t find a solution until now.

My solution has been to use the node-sonos-http-api running on a Raspberry Pi and using cron. Very simple really. Basically the node-sonos-http-api offers up a local HTTP server on port 5005 that accepts GET requests to perform actions on players such as playing, tuning in to Tunein stations, joining groups etc. So I have a couple of cron jobs that first thing makes sure the bathroom player leaves any other group it might be in, sets the volume and then tunes into the radio station. Later the kitchen players volume is set and the player joins the bathroom player and so on. Very cool and works like a charm.

The biggest problem turned out to be getting node and npm installed on the Raspberry Pi v.2 I’m using but downloading the binaries manually and installing manually (unzipping really) instead of using apt-get worked like a charm. Then I simply run the node-sonos-http-api server on startup and have cron do the requests using curl chaining multiple requests together using && where necessary i.e. when I need to change volume and join a group in one cron job.

Fixing Heroku and SFDX CLI after upgrading to macOS High Sierra

macOS was just recently approved by Salesforce IT so I upgraded but only to find that my heroku CLI and SalesforceDX CLI tools had stopped working. I seem to remember that SalesforceDX is basically the same as the Heroku CLI so them failing together made sense. Running the tools only gave strange errors…

$ heroku
    stat /Users/mheisterberg/.local/share/heroku/client/bin/heroku: not a directory
    fork/exec /Users/mheisterberg/.local/share/heroku/client/bin/heroku: not a directory
$ sfdx
    stat /Users/mheisterberg/.local/share/sfdx/client/bin/sfdx: not a directory
panic: fork/exec /Users/mheisterberg/.local/share/sfdx/client/bin/sfdx: not a directory

goroutine 1 [running]:
panic(0x259de0, 0xc420017350)
	/usr/local/go/src/runtime/panic.go:500 +0x1a1
main.must(0x3c03c0, 0xc420017350)
	/home/ubuntu/.go_workspace/src/ +0x5c
main.getExitCode(0x3c03c0, 0xc420017350, 0xc420017350)
	/home/ubuntu/.go_workspace/src/ +0x12b
	/home/ubuntu/.go_workspace/src/ +0x14c

I started thinking it was an issue with node but it turned out to be caused by the command line tools for macOS having been uninstalled or needing to be updated. Below are the steps I used to install the command line tools, upgrade node (I’m using Homebrew) and fix the Heroku CLI and SalesforceDX CLI.

// update / install command line tools for macOS
$ xcode-select --install

// update homebrew
$ brew update

// verify my node version
$ node --version

// upgrade node
$ brew upgrade node
==> Upgrading 1 outdated package, with result:
node 9.3.0_1

// now to the real magic - fix heroku cli
$ rm -rf ~/.local/share/heroku/client
$ heroku update
heroku-cli: Updating to 6.14.43-73d5876... 12.7 MB/12.7 MB
heroku-cli: Updating CLI... already on latest version: 6.14.43-73d5876
heroku-cli: Updating plugins... done
$ heroku --version
heroku-cli/6.14.43-73d5876 (darwin-x64) node-v9.2.0

// rinse and repeat for SalesforceDX cli
$ rm -rf ~/.local/share/sfdx/client
$ sfdx update
sfdx-cli: Updating to 6.0.26-3d23012... 19.3 MB/19.3 MB
Installing dependencies for /Users/mheisterberg/Programming/repos/sfdx-l18n-plugin... done
sfdx-cli: Updating CLI... already on latest version: 6.0.26-3d23012
sfdx-cli: Updating plugins... done
$ sfdx --version
sfdx-cli/6.0.26-3d23012 (darwin-x64) node-v8.6.0