myUplink Token Renewal Issues

At noon on Thursday 18th December the data for the NIBE Ground Source Heat Pump stopped updating onto heatpumpmonitor.org. Some of this data is sourced from the Heat Pump Controller, which only uploads it to NIBE’s myuplink.com so the required parameters need to be downloaded from there. The remainder of the data is sourced ‘locally’ – from heat meters and electricity meters – then all the data required by heatpumpmonitor.org is uploaded together.

HeatpumpMonitor.org graph not updating after noon on 2025-12-18

There are a few possible reasons for the lack of updates so once I’d noticed the issue I did a few checks:

  • Was my heatpumpmonitor ‘uploader’ script still working?
    • Yes and no: it was being invoked every minute as expected but it was failing to find any recent myUplink data to upload – which suggested a problem with the download from myUplink.
  • Was the myUplink ‘downloader’ script still working?
    • It was running but it was failing, with an error message (from the Python code that handles the OAuth2 Authentication):
oauthlib.oauth2.rfc6749.errors.TokenExpiredError: (token_expired)

The myUplink website and app were working fine, indicating that the heat pump was ‘online’ and showing recent data and graphs – so the data was getting to myUplink OK but the script that calls the myUplink API to download the data wasn’t successfully Authenticating, because it was presenting an ‘expired’ token.

Expiry of the tokens used for OAuth2 Authentication is perfectly normal; they have a relatively short lifetime of 3600 (seconds, i.e. 1 hour) and need to be renewed once they expire. Renewal is normally automatic, using the auto_refresh_url and the refresh_token to do that.

I had a vague recollection of this happening before, which led me to go through the process of creating and authenticating new application ‘secrets’ but I thought that didn’t help with having the tokens auto-renew. After a few days everything started working again so I assumed there had been a fix applied at the myUplink server end. However, it’s now been three days since the download API calls worked which feels like enough time for the myUplink administrators to have spotted an issue – although half of that time has been on the weekend.

Maybe trying to Authenticate a new Application will highlight a wider issue – or alternatively, if that works, it will show that re-Authenticatng the existing application will also work?

Using a new Application (i.e. with a different Client ID and Client Secret) worked OK – but that’s not actually testing token renewal so I need to wait for the token to expire and test it again.


Two hours later and the new Application happily renewed its (by then) expired token. Swapping the existing script over to the new Application credentials has made those spring into life and now data is flowing again.

So it looks like the Application credentials need refreshing periodically. Perhaps the refresh_token has its own expiry period? Looking back at some old files, there is a suspicious-looking date stamp of 18 Dec 2023 on one of the saved token files, which hints at a 2-year expiry period for the refresh_token.

If that’s the case, it should stop working again on 21 Dec 2027.

Stored Hot Water Heating Economics

With the 5.4kWp solar PV installation on the House, receiving 2017-baseline Feed In Tariff payments with 50% “Deemed Export”1 it made sense to use the immerSUN intelligent solar PV diverter to drive the hot water cylinder’s immersion heater with “excess” solar generation – i.e. what would otherwise have been exported to the grid. This provided zero-cost hot water throughout the Summer and for most of Spring and Autumn, enabling the heat pump to be turned off at the mains for half of the year (saving on its standby power consumption).

The immerSUN works by using a CT clamp to measure the flow of electricity to and from the main electricity meter and treating the immersion heater like a dimmable light, feeding that with just enough power to maintain a small (configurable) export to the grid. The thermostat on the immersion heater is set to cut out at 60°C so on sunny days the hot water cylinder has been heated to 60°C by the end of the day.

The heat pump is configured to only heat hot water between 00:00 and 06:00 (to coincide with the low-rate electricity tariff period) and is set with a tank temperature target of 50°C, which works well in conjunction with the immerSUN:

  • If there has been enough sunshine to let the immerSUN do its thing, the hot water is already over 50°C at 00:00 so the heat pump does nothing
  • If there has not been enough sunshine and the hot water cylinder is below 50°C the heat pump will run a DHW cycle overnight, ensuring there’s enough hot water for showers in the morning

Mostly this works fine without any intervention, but moving into Autumn there are times when there’s not enough excess solar generation to heat the hot water cylinder – and if the heat pump is still switched off at the mains (because there’s no need for space heating) it can’t kick-in overnight and the hot water cylinder can cool to 30°C or less, making for cold showers.

A complication is that the ‘best’ monitor of the temperature of the hot water cylinder is the heat pump, which has one temperature sensor in the middle and another nearer the top – but if the heat pump is switched off at the mains those don’t work. As mitigation, there’s a second temperature sensor in the middle pocket which is independent of the heat pump – a DS18B20 which is connected to the OneWire interface on a Raspberry Pi that also reports the temperatures in the MVHR ducts (using some more DS18B20 sensors). This additional sensor is visible to Home Assistant (via MQTT) so it would be possible to create an alert if the hot water cylinder is too cold – or automatically ‘boost’ the immerSUN or something.

With the construction of the Outbuildings, it’s time to review whether to retain the current approach or to change to something different, given that:

  • The Feed In Tariff “Deemed Export” arrangement has already been replaced with “Negotiated Export”, where the energy supplier pays for exported electricity as measured by the Smart Meter
    • The payments depend on the selected Export Tariff but Octopus Energy’s “Outgoing Octopus” pays a flat rate of 15p per kWh exported
  • The immerSUN’s CT clamp is actually measuring the electricity flow to and from the House, rather than to and from the Meter – and when the Outbuildings are connected to the same Meter those readings will no longer match
    • In principle the CT wiring could be further extended to measure at the actual Meter – but that would require roughly an additional 75m of cabling to be routed to and through the Outbuildings
  • The Outbuildings will add a further 11kWp of solar generation capacity – as well as about 30kWh of battery storage capacity
    • On the one hand, that means there will be a lot more “excess solar generation” available to power the immersion heater – but on the other hand, using any excess to charge the batteries would be a “better” use for that energy than directly driving an immersion heater
    • The battery charging algorithm will be doing the same thing as the immerSUN is trying to do – using up “excess” solar generation (to charge the batteries) – so the two algorithms will be “competing” for this excess and might end up interfering with each other, setting up some sort of oscillation perhaps
      • Both algorithms have a configurable “minimum export” setting though, which could (actually, should) be used to deliberately give one unit priority over the other
      • Just to further complicate matters, the Outbuildings will also have two Zappi EV charge points, which can also be configured to send excess solar PV generation to an EV, so the “minimum export” setting for those needs to be considered too

From a purely financial standpoint, giving up 15p per kWh of export payments during the daytime in order to heat water at 100% efficiency versus paying 7p per kWh to import electricity overnight and heat water with the heat pump at 330%2 efficiency (i.e. effectively 2.2p per kWh of hot water) is not cost effective. However, it does guarantee the water heating is zero-carbon. The addition of battery storage will enable zero-carbon energy generated on-site during the daytime to be used overnight though.

In summary, on the current electricity tariff (with 15p per kWh of export and 7p per kWh of overnight import) it will be best to stop using the immerSUN and swap to using the heat pump overnight to heat stored hot water. The main exception to that will be in perfect solar generation conditions when the theoretical maximum of 16kW is being generated, resulting in curtailment of solar generation – because of the limits on site export (6kW) and battery charging (8kW3) – in which case that power will again be “free” since it’s not possible to be paid for exporting it. To do that ‘properly’ implies:

  • Relocating the immerSUN unit’s CT clamp to measure the overall site export
  • Raising the ‘minimum export’ limit on the immerSUN to something much higher – close to the maximum permitted 6kW

In the interim, simply raising the immerSUN’s ‘minimum export’ limit (and not relocating the CT clamp) will probably be sufficient – taking advantage of the fact that the solar array on the Outbuildings is also facing due South and will typically generate twice as much as the solar array on the House. If the House is exporting more than 4kW then the solar array on the House must be generating about 4.65kW which implies the solar array on the Outbuildings is generating about 9.3kW – i.e. about 13.95kW in total, which is approaching the ‘curtailment’ point (14kW). It turns out the maximum configurable ‘minimum export’ limit for the immerSUN is exactly 4kW anyway.

  1. The assumption that 50% of generated electricity will be consumed on-site and 50% will be exported to the grid ↩︎
  2. The actual, measured Seasonal Performance Factor when using the heat pump to heat DHW to 50°C (rather than for space heating) ↩︎
  3. It’s not entirely clear whether the 8kW limit specified for charging the Tesla PowerWall 3 – with an expansion battery pack – applies to charging from the Grid (AC) or charging from Solar (DC) ↩︎