Hacking the Worcester Wave thermostat in Python – Part 3
So, last time we worked out how communications were encrypted and managed to read the current status of the heating system (whether the boiler is on or not, the current temperature, and so on). That’s great – but it’d be even better if we could actually control the thermostat from Python: set the temperature, change from timer mode to manual mode etc. That’s what we’re going to focus on today.
So, using the same ‘man-in-the-middle’ approach I monitored the communications from the app as I changed various settings. When changing the temperature I got a message like this:
<message id="lj8Vq-31" to="rrcgateway_458921440@wa2-mz36-qrmzh6.bosch.de" type="chat"><subject>/heatingCircuits/hc1/manualTempOverride/temperature</subject><body>PUT /heatingCircuits/hc1/manualTempOverride/temperature HTTP:/1.0\nContent-Type: application/json\nContent-Length: 25\nUser-Agent: NefitEasy\n\n\n\nXmuIR7wCfDZpPrPkrb/CqQ==\n</body></message>
Again, tidying it up a bit, and removing the XMPP headers we see the body is:
PUT /heatingCircuits/hc1/manualTempOverride/temperature
HTTP:/1.0
Content-Type: application/json
Content-Length: 25
User-Agent: NefitEasy
XmuIR7wCfDZpPrPkrb/CqQ==
If we decode the text at the bottom we find that it decodes as:
{"value":16}\x00\x00\x00\x00
This looks like JSON, with a bit of null-padding at the end (presumably so that the encryption routine is given data with the length divisible by a certain number) – and it makes sense, as I set the thermostat to 16 degrees.
So, if we send this message (but with a different number) then presumably the temperature setting will change? Well…sort of!
You see, changing the temperature depends on what mode you are in. There are two modes, and the UMD part of the status message tells you which one you are in: manual or clock. If you’re in manual mode then you can change the temperature by simply sending a PUT message (like the one above) to /heatingCircuits/hc1/temperatureRoomManual
, with JSON of {"value":21}
(or whatever temperature you want).
However, if you’re in clock mode then you have to set the ‘override temperature’ (a PUT message to /heatingCircuits/hc1/manualTempOverride/temperature
) with the same JSON as above, and you then have to turn the ‘temperature override function’ on (a PUT message to /heatingCircuits/hc1/manualTempOverride/status
with the JSON {"value": "on"}
).
Oh, and if you want to change the mode then you can just send a PUT message to /heatingCircuits/hc1/usermode
with the JSON {"value": "clock"}
or {"value":"manual"}
.
You may be wondering whether you get a response from these messages or not: you do, but they’re not very interesting. Unless there has been an error, all you get is:
No Content
Content-Type: application/json
connection: close
There are loads of other messages you can send to do all sorts of complicated things (such as changing the timer programme), but I haven’t bothered to investigate any of those yet. I know they will use the same format as these messages, they’ll just have slightly more complicated JSON payloads, and may require the sending of multiple messages. I’m just happy that I can read the status of my thermostat, and control basic settings (mode and temperature)!
So, I haven’t actually mentioned Python that much in this series so far (sorry!) – although, in fact, most of my ‘trial and error’ work was done through Python using the great sleekxmpp library. I have to confess here that I haven’t written the code as well as I should have done: I should really have designed it to implement a proper Finite State Machine, and send and receive the appropriate messages at the appropriate times, all while updating internal information in the Python classes…but I didn’t! Sorry – dealing with all of that, working asynchronously, was too much like hard work.
So, I wrote a BaseWaveMessageBot
class that implemented connecting, sending messages, encoding and decoding message payloads and a bit of simple error handling. That class has all of the complicated stuff in it, so I then wrote a couple of very simple classes (StatusBot
and SetBot
) that send the appropriate messages and process the responses. I then combined these in a nice class called WaveThermo
. Currently there aren’t many methods in WaveThermo, but I will gradually add more functionality as I need it.
The code is available on Github and is fairly easy to use:
Of course, I’ve only tested it with my thermostat – so if it doesn’t work for you then please let me know!
So, that’s it for this time – next time I’ll talk about a bit of the work I’ve done with automated monitoring of the temperature and the thermostat state, and some of the interesting patterns I’ve found.
If you found this post useful, please consider buying me a coffee.
This post originally appeared on Robin's Blog.
Categorised as: Home Automation, Programming, Python
Ooh, bookmarking with eagerness to see part 4, though this is already very useful (I don’t know any python or how to use it, but I’m pretty certain I could learn enough visual basic to knock together a hokey-cokey program that can access my Wave… it doesn’t need to be fast or pretty after all, just good enough to spit out some encrypted strings and interpret those that come back…).
Funnily enough, I came across this because I fancied setting up a temperature tracker using the ‘stat and I was kinda frustrated at the lack of a general web interface (maybe I could even make one with php?) and how limited the existing app is. It’s not at all bad, but the various kind of “smart meter” abilities I thought might be built into it are seriously lacking; the usage tracker that it does have is pretty token after all, and without anything to properly compare to isn’t going to be much use until at least a year has gone by. Plus you can’t easily break it down week by week, see how changing ambient temperature (or stat settings) affect the cost, etc. Or even get an idea of how far ahead you need to set it in order to achieve the set temperature at the right time (the learning feature is all well and good but how do you know it’s working right?). All that kind of stuff that would be very easy to deal with if only you could regularly poll it and shunt the logged data into a spreadsheet.
(On that note, I really could do with getting back on with the project re: finding some way to, at long last, interface my Eon proto-smartmeter thing with a computer, so both gas and electric would be covered… it even came with a cable, that supposedly bridged USB to its RJ11 serial port, but the damn software was so buggy that it wouldn’t even install)
One thing I wonder if you’ve looked at in all this – as the Wave itself is wifi, and thus would have to get through your pretend “router” just the same as the phone would, have you looked at the data going back and forth from that? Being able to ping it directly would save quite a bit of in and out traffic, and not bother Bosch quite so much (and they might start wondering wtf you’re up to, grabbing information from the thing on a very very regular 60-second basis or whatever). Plus there’s the small matter of whether they’re gathering all the data that’s going back and forth between you and the stat and whether that can be used for any nefarious profiling purposes…
Who knows, the stat itself might even be shooting plaintext back and forth 😀 though I doubt hashing a few hundred characters is beyond the reach of a typical microcontroller that can manage to communicate across the web anyway. And there might be a whole load of other data that it’s emitting that gets filtered or concatenated on the server before being sent back to the client app. Why pretend to be the android client when you could just pretend to be the server itself?
Hi! Thanks for the interest.
You’ve reminded me that I really should write part 4 – but that requires remembering how I set things up etc! I did some interesting things with the data, for example looking at the rate of heat loss from the house before and after cavity wall insulation and so on.
In terms of ‘smart-ish’ meters: I’ve done some work connecting a CurrentCost meter to the computer (see https://blog.rtwilson.com/how-to-log-electricity-usage-from-a-currentcost-envir-part-1/), and some of those techniques may work (specifically, you may find that the USB connection shows up as a serial device and then you can just send and receive nice simple ASCII strings).
In terms of sniffing the traffic from the Wave to the router, rather than capturing it from the phone: I did try that, but didn’t get very far. My memory of it is a bit hazy (I really should keep better notes…), but I think that traffic was encrypted and I had no way to install a ‘fake’ certificate on the Wave, so I couldn’t decrypt it. That’s why I ended up going for the phone traffic, as I could intercept that far more easily. However, I am possibly meeting some people from Worcester Bosch later in the summer to discuss some of the stuff I’ve done – so I’ll definitely mention this (and more…) then and see what comes of it.
…as well as what data the app receives to build its energy usage graph
*refreshes*
…ah, that’s quite a neat use for it 🙂 I was mainly after just seeing how the peak and trough temperatures varied across the day and seasons, and when they occurred, to figure out which side was getting (or losing) the most heat, and whether it would work better to invest in a small aircon or dehumidifier unit for the unreasonably sweltering summer days (top floor flats appear to sink an awful lot of damp heat, and fans do pretty much nothing to help), or just staple duvets to the wall then come up with some kind of automated blackout/reflective blind that would whirr into place after the time I usually leave if the weather report came up hot and sunny…
(and of course it might be possible to get better control over the operation of any cooling device using that central stat instead of whatever it has built-in, like using the weather prediction or something to work out when it would be worth turning on early to pre-cool if the day is likely to get hot enough that it otherwise wouldn’t be able to maintain a comfortable temperature, or to not turn on at all if it’s going to get hot at first but then turn to torrential rain and drop 10 celcius naturally)
And yes, my meter is essentially a Currentcost (in fact, I think we somehow ended up with two different generations of it at one point, one Eon branded and the other just being a generic CC), but the problem I think probably lies more in the adaptor than the device. Can’t get windows to make any sense of it. If however it really does just use RS232 over a jack instead of a normal plug, I can probably get hold of a suitable converter lead (odd the little bits and pieces that turn up as “spare junk” where I work, when it’s time to load old servers and the like into the catapult and fire them into the sun…), and reasonably reliable Prolific-based USB/Serial converters are basic commodities these days. Can just fire up some freeware terminal and fire bytes at it by hand if needed, then; have diagnosed and fiddled with enough other bits of hardware that way. Might not be much use for actual data logging, unless I just set it up to continually squirt the current stats every few seconds as CSV, then run a looooooong serial cable from where it is to a hub and leave the terminal logging the output to a file…
Shame about the certificate thing btw, didn’t realise it was something you had to install on the client as well as just fake on a server. Oh well 🙂 Maybe someone somewhere will figure out how to crack the service mode, find out it’s just a regular ARM or even Android device, and root it…
Be careful about meeting the Bosch guys, they might be using it as a pretence to have you arrested for hacking their stuff, or maybe just have the Boiler Mafia put a hit on you 😀
In fact I do kinda wonder if it might just be easier to figure out what the CC’s mains clamp transmits and on what frequency, because neither of them strike me as massively sophisticated devices (would an energy co give away anything expensive?) and anything the meter panel can calculate and log, your computer can as well… and if it’s going to be on 24/7 for any other reason, it may as well do that at the same time. It can even keep going in a power cut or in case of the plug ring breaker tripping if it’s a laptop, which the meter definitely doesn’t…
…so I googled a couple interesting looking terms. Maybe the following isn’t news, but… eh.
1/ Go search for “NefitEasy”. The results might be useful/interesting to you 😉
2/ JSON appears to be potentially more full of holes than a swiss cheese, unless whoever’s implemented it has been scrupulously careful. If you’re feeling particularly ballsy, try injecting some code that could crash whatever’s reading it at the other end (either the server’s Javascript process, or your ‘stat) and seeing what happens. If the Bosch guys ask “was it you that did… you know… the thing?”, deny all knowledge until they’ve had at least two beers each.
see https://github.com/robertklep/nefit-easy-core
and https://github.com/robertklep/nefit-easy-commands and https://github.com/robertklep/nefit-easy-http-server
have fun!
HI Robin,
This is excellent!!!!! 🙂 I have been trying to get my boiler to work with an underfloor system for years (my controls use the Worcester Bosch Bus and didn’t want to ditch them for the more clunky 240volt on / off variety). So have worked independently on timers so the heating overlaps.
I have just upgraded from the earlierer bus control to a new Wave and your work could solve this. My thinking is using something like a Raspberry Pi to coordinate the Worcester Wave with a couple of Nest Thermostats via their API.
Would you mind sending me your email when you have a moment for a few questions? I promise not to hound you (like others) for Part 4 too much!
Kindest,
Jonathan
Hi,
Glad this is useful. Feel free to email me on robin@rtwilson.com, though I can’t promise I’ll be much help!
Part 4 will be coming…sometime…!
Robin
Hi great stuff, I downloaded the NEFIT EASY Bosch app (100k downloads) which is the direct European version of the Worcester Wave app (10k downloads)..
https://www.domoticz.com/forum/viewtopic.php?f=17&t=9653#p67440 looks like our European friends have jail braked it.
Great article! With new things coming like Google Home and Amazon Echo I am hoping to do my own integration between the wave and one of them (probably the echo as Google Home does not seem to be getting an api – fools!).
This gives a great head-start; many thanks!
Does anyone know if the Nefit Easy Homebridge plugin works with the Wave?
For Siri – Wave integration.
Did anyone find a solution for this? I am hoping to be able to call an API using C# to set temperature using my Worcester Wave. The plan is to be able to control it using my Amazon Echo.
Fantastic work.
Have just downloaded your code and have tested it with my Wave controller and all works great. Now to see if we can integrate with IFTTT.
Hi,
yeah this is brilliant work, in-fact almost swung my decision to get the wave. I’ve worked out how to add some additional SET’s but cannot work out how to add more GET requests, for outdoor temp for example. I’ve built a simple API to sit in front of your scripts so I can drive it from openhab. any pointers?
thanks
I’m just hoping that it eventually gets some kind of compatibility with other home automation standards and apps … Nest et al … or even Bosch’s own one which doesn’t seem to want to know anything about the boilers at all! (FFS…)
It works great.
Very good article.
Thanks!
Has something changed at the bosh end? I’m getting errors: ssl.SSLError: [SSL: SSL_HANDSHAKE_FAILURE] ssl handshake failure (_ssl.c:1942)
anyone else having this issues?
Thanks for reporting this – I’ve just found that I’m getting the same error. (I didn’t notice earlier as we’re not using the heating at this time of year, so I hadn’t been using my code for a while). I’ll try and look into it and work out what is going on, but the error doesn’t seem very helpful and I’m not really sure where to start. I’ll update you here if I manage to fix it.
Aha, I’ve managed to fix it. I think Bosch have turned off SSL for the XMPP connections that are made ‘behind the scenes’, so I’ve turned that off too and it seems to work fine. The updated code is on the Github repo at https://github.com/robintw/pywavethermo, and you can see the (tiny) change at https://github.com/robintw/pywavethermo/commit/52b71d26eab90a1e6f730b722e46ea5ff9faa785.
Wow this is fantastic. All I want to do is download my usage data but this work is marvelous. Thanks for taking the time to publish all your efforts. I don’t understand it all but, I will step through your blogs again an I’m sure I’ll catch up eventually.
[…] time – but I’ll leave the description of that to later in the series. In the next part (Part 3) we’re going to look at sending messages to actually change the state of the thermostat […]