Automatic Power Move Calculator beta testers required

Userlevel 3

NOTE: this requires a few steps and you need to create a bookmark with the code in it below so it might not be for everyone.

I’ve created a javascript program that uses data from Ovo’s data api to try and work out your current and previous month’s target.

It’s as ugly as hell but does the trick. The javascript is also ugly as I wanted it to minify as best as possible so everything is global.

If somebody wants to check over the code to make sure it’s not malicious then please do and comment as if I knew nothing about javascript and somebody asked me to do this I’d be like no thankyou!

First create a bookmark with this as the content and call it something like “Ovo Calc”

javascript:async function main(t=0){for(fdld=firstday_lastday(t),total427=0,total=0,dow=fdld.fdom,year=fdld.year,mth=pad(fdld.month),l("Month: ",fdld.mthName),o("Month: "+fdld.mthName),i=1;i<=fdld.ldom;i++){if(dow>0&&dow<6){if(dts=`${year}-${mth}-`+pad(i),bhdates.includes(dts)){l("bank holiday "+dts);continue}if(furl=url+dts,data=await fetch(furl),!0!==data.ok){l("bad response for",furl);continue}if(spin(),json=await data.json(),json.electricity){for(,ed instanceof Array!=0&&48==ed.length||l("1/2 hoursly data is not an array or of wrong length",ed),e427Tot=0,dayTot=0,hh=0;hh<ed.length;hh++)dayTot+=ed[hh].consumption,d2d=new Date(ed[hh].interval.start),tsh=d2d.getHours(),0!=d2d.getTimezoneOffset()&&tsh++,tsh>=16&&tsh<19&&(e427Tot+=ed[hh].consumption);if(total+=dayTot,total427+=e427Tot,l(`${i} day ${e427Tot.toFixed(3)} / ${dayTot.toFixed(3)} %`,(100*e427Tot/dayTot).toFixed(3)),!0!}}dow=++dow%7}lm=`TOTAL Month %${(total427/total*100).toFixed(2)}  [${total427.toFixed(3)} / ${total.toFixed(3)}]`,l(lm),o(lm)}function firstday_lastday(t=0){return date=new Date,first=new Date(date.getFullYear(),date.getMonth()-t,1),last=new Date(date.getFullYear(),date.getMonth()-t+1,0),{fdom:first.getDay(),ldom:last.getDate(),month:first.getMonth()+1,mthName:first.toLocaleString("default",{month:"long"}),year:first.getFullYear()}}function set_acct_num(){return c=Object.fromEntries(document.cookie.split("; ").map((t=>t.split("=")))),v=c.mp_457e7322cdf0dcb51030b6a3bafd8805_mixpanel,!(void 0===v||(acct=JSON.parse(decodeURIComponent(v)),acctid=acct["Account Id"],!acctid))}function o(){for(q of arguments)nd=document.createElement("div"),nd.innerHTML=q,msgs.append(nd)}function setup(){document.body.innerHTML='<div>Working: [<span id="X">+</span>]<p><div id="msgs"></div></div>',mDiv=gid("msgs"),xDiv=gid("X")}function spin(){spx=!spx,xDiv.innerText=spx?%22%E2%97%89%22:%22%E2%97%8E%22}zone=%22england-and-wales%22,l=console.log,pad=t=%3E(%220%22+t).slice(-2),gid=t=%3Edocument.getElementById(t),bhdates=[],spx=0,url=%22,liUrl=%22,errLgin=t=%3Eo(%27%3Cb%3EERROR:%3C/b%3E%20[%3Ca%20href=%22]%27),errLoc=t=%3Eo(%27%3Cb%3EERROR:%3C/b%3E%20%3Ca%20href=%22,(async()=%3E{if(setup(),set_acct_num())if({url=url+acctid+%22?date=%22;try{if(bhr=await%20fetch(%22,bhr.ok){for(d%20of(bh=await%20bhr.json(),bh[zone].events))bhdates.push(;l(%22got%20bank%20holidays%22)}}catch(t){o(%22Can%27t%20process%20bank%20holidays%22)}o(%22Press%20F12%20for%20more%20info%22);for(let%20t=0;t%3C6;t++)await%20main(t)}else%20errLoc();else%20errLgin()})();


To use it first log into your Ovo account, then go to and then click on the bookmark you’ve created.  If you haven’t done either it’ll put up links to make things easier.

It’ll work backwards  from the current month trying to work out your percentage in the 4 to 7 zone for that month.  Bank holidays are accounted for.

NOTE:  The code is set to get bank holidays for England and Wales, you can change that to ‘scotland’ or ‘northern-ireland’ in the code.

If you’ve got the results of previous power move targets can you please tell me how close the figures this calculates are to it.  I’ve got two months bang on and 4 close but not exact to what Ovo have said - but I’ve had 2 different result from them for the same month.

As a note to anyone looking at the code I noticed while testing that British Summer Time figures in the data are offset by an hour so even if in the data it says it starts at 16:00 really that would be an hour later.

Here’s the code unminified:

zone="england-and-wales";// scotland northern-ireland
l=console.log; pad=a=>("0"+a).slice(-2);gid=x=>document.getElementById(x);
errLgin=x=>o('<b>ERROR:</b> [<a href="">CLICK HERE to sign into your Ovo account first.</a>]');
errLoc=x=>o('<b>ERROR:</b> <a href="">CLICK HERE</a> ignore the onscreen message then try again.');

(async ()=>{

if (!set_acct_num()) {errLgin(); return;}
if ( != "") {errLoc(); return;}

try {
bhr = await fetch("");
if (bhr.ok) {
bh = await bhr.json();
for (d of bh[zone].events)
l("got bank holidays")
} catch (e) {
o("Can't process bank holidays")

o("Press F12 for more info");
for(let m=0; m<6; m++)
await main(m);

async function main(mPast=0) {
fdld = firstday_lastday(mPast);

total427 = 0; total = 0;

l("Month: ", fdld.mthName);
o("Month: "+fdld.mthName);

for (i = 1; i <= fdld.ldom; i++) {
if (dow>0 && dow<6) {
dts = `${year}-${mth}-`+pad(i);
if (bhdates.includes(dts)) {l("bank holiday "+dts); continue;}
data = await fetch(furl); // ok: true or status: 200 check
if (data.ok !== true) {
l("bad response for", furl)

json = await data.json();

if (json.electricity) {
ed =;
if (ed instanceof Array == false || ed.length != 48) {
l("1/2 hoursly data is not an array or of wrong length", ed);
e427Tot = 0; dayTot = 0;
for(hh=0; hh<ed.length; hh++) {
d2d = new Date(ed[hh].interval.start);
tsh = d2d.getHours();
if (d2d.getTimezoneOffset() != 0) tsh++;
if (tsh >= 16 && tsh < 19)
total += dayTot; total427+=e427Tot;
l(`${i} day ${e427Tot.toFixed(3)} / ${dayTot.toFixed(3)} %`, (100 * e427Tot / dayTot).toFixed(3));
if ( !== true)
dow = ++dow%7;
lm = `TOTAL Month %${(total427/total * 100).toFixed(2)} [${total427.toFixed(3)} / ${total.toFixed(3)}]`;

function firstday_lastday(mthOffset=0) {
date = new Date();
first = new Date(date.getFullYear(), date.getMonth() -mthOffset, 1);
last = new Date(date.getFullYear(), date.getMonth() -mthOffset + 1, 0);
let p = {
fdom: first.getDay(),
ldom: last.getDate(),
month: first.getMonth() + 1,
mthName: first.toLocaleString('default', { month: 'long' }), year: first.getFullYear()}
return p;

function set_acct_num(){
c = Object.fromEntries(document.cookie.split('; ').map(c => c.split('=')));
v = c.mp_457e7322cdf0dcb51030b6a3bafd8805_mixpanel;
if (v !== undefined) {
acct = JSON.parse( decodeURIComponent(v) )
acctid = acct["Account Id"];
if (acctid)
return true;
return false;

function o() {
for(q of arguments){
nd=document.createElement("div"); nd.innerHTML=q;

function setup(){
document.body.innerHTML = '<div>Working: [<span id="X">+</span>]<p><div id="msgs"></div></div>';

function spin() {
xDiv.innerText = spx?'◉':"◎";


14 replies

Userlevel 3

I’ve put the code for the bookmarklet and the unminified code on github.  Easier than posting here.

If I find any problems I’ll post info here.

So far these are the results of my calculator vs the Power Move emails.  The figures on the right were the successfully hitting targets and a roundup email came with October, November and December results.


My Calc vs Email figures

     Mine | Theirs

Oct 10.29 | 10.92 (success email 6th Nov and roundup email)

Nov  8.80 | 8.80 (email 3rd Dec 23 and roundup email)

Dec  9.85 | 10.02 (9.85 in roundup, 10.02 in success email 8th Jan)

Jan  8.03 | 8.04

Feb 10.52 | 10.52

Userlevel 7

Not working for me on Edge 124 on Windows 11, I’m afraid:



Userlevel 3

Yeah, it’s dead in the water on Edge, working fine on Brave.  Haven’t tested it anywhere else.  At the moment it’s working for me and I’ve currently got no incentive to get it working on other platforms but if I do I’ll update here.


Another member has tested it and spotted an error which helped me fix it and now their figures match bang on with that the code produces.  Thanks to them for that.

Userlevel 7

So Brave has a laxer approach than Edge to browser security? I see that the first element in the smartpaymapi page is 

<meta http-equiv="Content-Security-Policy" content="default-src 'none'; require-trusted-types-for 'script'">

and MDN have this documentation: TrustedHTML - Web APIs | MDN (

All way over my head, I’m afraid.


Userlevel 3

With Edge getting the code working with TrustedHTML and outputting to the page was easy to get past but there’s a content security issue after that where not only am I not allowed to grab the bank holiday information I also can’t grab the Ovo info.

I abandoned doing full authorisation with javascript before but at some point I might.  I’m writing a lot of other stuff at the moment that I’d like to finish firlst.

Userlevel 3

Code Update:  I’ve updated the peak hour usage calculators to use the slots 6 to 9 after the first of April.

The monthly calculator won’t work in a lot of browsers - works for me in Brave, not in Edge.  If it works for you great, please say browsers that it’s worked and not worked in.


If it doesn’t work the calculator for the daily usage page should work.  Just save the text as a bookmark, go to a daily usage page and it’ll tell you the peak percentage for that day.  You can use the value in a spreadsheet for the month.  It’ll just save you time working out what the six important half-hourly slots add up to.


Ovo Power Move Calculator bookmarks.

Userlevel 3

I’m on Chrome (yeah, I know 🙄) on MacOS. The daily one works fine. The monthly one gives this error. Yes, I am logged in.


Working: [+]

ERROR: [CLICK HERE to sign into your Ovo account first.]

Userlevel 3

This is an exciting concept @Tron Burgundy! I hope you and the other members can make progress on this and it works on multiple platforms.

I will be checking back in to see how things are progressing for you 🙂

Userlevel 3

I’m on Chrome (yeah, I know 🙄) on MacOS. The daily one works fine. The monthly one gives this error. Yes, I am logged in.


Working: [+]

ERROR: [CLICK HERE to sign into your Ovo account first.]


Can you try clicking the link and logging into your account, then click the bookmark again - it should then link to the smartapi site, click the link then click the bookmark again.  I know it’s weird having to do it 3 times but doing it that way saves me tons of coding.

Hopefully you’ll end up with something like this:




Userlevel 3

I’m on Chrome (yeah, I know 🙄) on MacOS. The daily one works fine. The monthly one gives this error. Yes, I am logged in.


Working: [+]

ERROR: [CLICK HERE to sign into your Ovo account first.]


Can you try clicking the link and logging into your account, then click the bookmark again - it should then link to the smartapi site, click the link then click the bookmark again.  I know it’s weird having to do it 3 times but doing it that way saves me tons of coding.

Hopefully you’ll end up with something like this:




I did that. But that link isn’t taking me to the smartapi site, it’s going to


Userlevel 3

Ah, read the instructions this time!


Tried using the JS console, got a sht-tonne of error messages, starting with this…

Something might be messed up with JS on this browser. The add image button on this page doesn’t work either.  

Oh, do I need to turn on 3rd party cookies?

Userlevel 3


The monthly Power Move bookmarklet has been updated and now runs in Edge and possibly a few more browsers.  To get the bank holiday data to make the calculations more accurate it has to go through the step of jumping out to where it’s allowed to remotely grab the bank holiday info.  This means a few extra clicks but it’s worth it to have all the calcs done without having to pore over data.

Go here and copy the text (copy icon on the right) and paste it into a bookmark.

Copy icon in the middle​​​​

Then after that the steps are

  1. log into your Ovo account
  2. Click the bookmark
  3. Click the link shown and on the empty page click the bookmark again, don’t just gawp at the sea of white.
  4. Click the bookmark for the last time when returned to Ovo.

You should get something like this:


I know it’s a bit of a faff but it’s free and it saves a lot of piddling around with doing the calculations yourself.

Please let me know if it works/doesn’t work and what browser you’ve used.

Userlevel 3

Sorry to post again but I couldn’t edit above.  There’s now a version that’ll save a click or two.  With this saved as a bookmark you can just sign into Ovo, click the bookmark and then click the bookmark again.  You should see after the first click that there’s bank holiday data in the url.

Ovo-Power-Move-Calculator/ovo-FAST-calc-bookmarklet.txt at main · Tron-Burgundy/Ovo-Power-Move-Calculator (


@ChristopherS_OVO , @joanx it might work for you now, hopefully.

Userlevel 7

@Tron Burgundy That is brilliant - thanks so much. Now I see why you should get out more.

It’s WAD on Edge 125, despite lots of CS warnings, and the results are identical to my own, to the nearest Wh. The only blemish I’ve noticed is the misplaced square bracket before kWh: I think you meant to have … 10.280 kWh] - bank … instead of the current … 10.280]kWh - bank… 
Before and after pics:

I’m itching to plug in a few lines of CSS to prettify the results page - the sort of task that can keep me occupied for a whole bank holiday. I’ll share if and when …