Tuesday, 18 July 2017

Alexa-ing the Worcester Wave

This page still gets a few hits per day, so I've broken out the steps and example code into a bitbucket repo. If that's all you're after then head over there now --> https://bitbucket.org/iainxyz/wave-via-ifttt/


Our new boiler came with one of those WiFi thermostats that everyone has these days. Unfortunately, not a Nest, as that would have knocked a couple of years off the guarantee. So I went with the sensible OEM option and ended up with a Worcester Bosch Wave.
While it does come with a half decent smartphone app, it doesn't appear to be compatible with Google Assistant, Alexa, IFTTT or any other third party do-things-with-stuff type services. Which is a shame - mainly because I just bought an Echo Dot on #primeDay!

Or so I thought...

After a bit of digging, I found that a few clever buggers have decompiled apps and used wireshark to build an API for them. But that means running it locally on a server, faffing with dynamic DNS and punching holes in router configs. All things I'd rather avoid doing...

A bit more digging revealed that the WB Wave is based on the hardware of a Dutch company called Nefit. And they do have an IFTTT channel. So thanks to Chrome's built in Google Translate, I registered my thermostat on the Nefit website and hooked up a quick Applet with the Alexa channel.

It all seemed to work. You couldn't specify a temperature, but a couple of phrases at each end of the spectrum would be enough. One to bump up the temperature, and one to drop it down.
"Alexa, trigger warm up the house"
"Alexa, trigger it's hot in here"
Any sane person would have stopped there. But I wasn't entirely happy with the flow of those commands. I knew that Custom Skills were a thing. And I remembered that IFTTT has a Maker channel which is essentially a REST API. How hard could it be!?

I found this great Pluralsight guide that is a little bit out of date, but all the key info is still there. How to host some code in a Lambda function on AWS, and link it to an Alexa skill.

So with a bit of help from w3schools and stack overflow, I set about modifying the 'Hello World' example and shoehorning in a POST to my maker channel endpoint.

There were only a few gotchas along the way...

Javascript callbacks completely flummox me. Always. My code was getting to the 'end session' command before it had even started sending the POST. A pretty simple one to solve, once I'd remembered what the problem was.

I then spent far too long trying to use the http module to make an https request and wondering why nothing I tried would work. Even specifying 'https' as the protocol and 443 as the port... Still nothing.

I swapped that out for `require('https')` after facepalming hard. Sorted. Idiot.

I was using Request Bin while I was tweaking and debugging. The requests were now coming through just fine so I swapped out the details for the Makers service and got nothing but errors.

Value1: none.

This one was a combination of trial and error in Postman and spot the difference. It turns out the Maker endpoint is really fussy about how it receives data. It must have the `content type application json` header. And all of the values in the body must be strings. Otherwise it just craps out.

❌ { "value1" : 12 }

✅ { "value1" : "12" }

I eventually got to the point where everything worked in test mode. The test tools on AWS Lambda and the Developer Console are really good. You can use the Service Simulator to pass example phrases to your function to see how they're handled. And you can use the generated request to test your function in isolation.

But Alexa refused to cooperate. No matter what or how I asked, I got one of the following answers:

"What device do you want to use?"
"I cannot find 'thermostat'."
"I'm not sure what you meant by that."
"I'm having trouble right now. Please try later."
"I'm sorry. I cant...."


Stack Overflow to the rescue once again! The default language on the Alexa Skills developer console is English US, but my Echo Dot is of course set as English UK. So I followed the advice of this answer (whilst identifying with the comments on it) and tried again.


I did a bit more tweaking once I got the hang of how the trigger word, intent and invocation phrases worked. So now you can say something like:

"Alexa, ask the thermostat for 14 degrees"
"Alexa, set the temperature to 14 degrees using the thermostat"

Here's the whole ridiculous chain from start to finish...

Alexa uses a custom skill that talks to a Lambda Function hosted in AWS.
That POSTs some JSON to the IFTTT Maker Channel Webhook.
Which is in an Applet that talks to the Nefit Channel.
Which is linked to the Dutch Nefit website.
Which just so happens to work with the WB Wave.

It takes a few seconds for the thermostat to update. Remember that episode of Big Bang Theory where they send a signal around the world to turn on their lamp? It's a bit like that.

So... Next steps.

Well, I need to take my developer hat off and do some testing now. There's literally NO error handling around it at all. I don't know what will happen if I try to set the temperature to 'aardvark'. Hopefully either the Nefit IFTTT channel or website will reject the request. I'm almost too scared to find out.

Almost. ðŸ˜‰

No comments:

Post a Comment