Skip to main content
Tron Burgundy
Rank 4
Rank 4
March 8, 2024

Automatic Power Move Calculator beta testers required

  • March 8, 2024
  • 36 replies
  • 735 views

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=json.electricity.data,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!==json.electricity.next)break}}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=%22https://smartpaymapi.ovoenergy.com/usage/api/half-hourly/%22,liUrl=%22https://account.ovoenergy.com/%22,errLgin=t=%3Eo(%27%3Cb%3EERROR:%3C/b%3E%20[%3Ca%20href=%22https://account.ovoenergy.com/%22%3ECLICK%20HERE%20to%20sign%20into%20your%20Ovo%20account%20first.%3C/a%3E]%27),errLoc=t=%3Eo(%27%3Cb%3EERROR:%3C/b%3E%20%3Ca%20href=%22https://smartpaymapi.ovoenergy.com/%22%3ECLICK%20HERE%3C/a%3E%20ignore%20the%20onscreen%20message%20then%20try%20again.%27),(async()=%3E{if(setup(),set_acct_num())if(%22smartpaymapi.ovoenergy.com%22==window.location.host){url=url+acctid+%22?date=%22;try{if(bhr=await%20fetch(%22https://www.gov.uk/bank-holidays.json%22),bhr.ok){for(d%20of(bh=await%20bhr.json(),bh[zone].events))bhdates.push(d.date);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 https://smartpaymapi.ovoenergy.com/ 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);
bhdates=[];spx=0;
url="https://smartpaymapi.ovoenergy.com/usage/api/half-hourly/";
errLgin=x=>o('<b>ERROR:</b> [<a href="https://account.ovoenergy.com/">CLICK HERE to sign into your Ovo account first.</a>]');
errLoc=x=>o('<b>ERROR:</b> <a href="https://smartpaymapi.ovoenergy.com/">CLICK HERE</a> ignore the onscreen message then try again.');

(async ()=>{
setup();

if (!set_acct_num()) {errLgin(); return;}
if (window.location.host != "smartpaymapi.ovoenergy.com") {errLoc(); return;}

url=url+acctid+"?date=";
try {
bhr = await fetch("https://www.gov.uk/bank-holidays.json");
if (bhr.ok) {
bh = await bhr.json();
for (d of bh[zone].events)
bhdates.push(d.date);
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;
dow=fdld.fdom;
year=fdld.year;
mth=pad(fdld.month);

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;}
furl=url+dts;
data = await fetch(furl); // ok: true or status: 200 check
if (data.ok !== true) {
l("bad response for", furl)
continue;
}

spin();
json = await data.json();

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

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;
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?'◉':"◎";
}

 

36 replies

Tron Burgundy
Rank 4
Rank 4
March 14, 2024

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.

https://github.com/Tron-Burgundy/Ovo-Power-Move-Calculator/blob/main/ovo-bookmarklet.txt

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
 

Firedog
Super User
Super User
March 14, 2024

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

 

 

Noel | I have no official status; I'm just a volunteer who comes here to help other customers. My gear: Aclara SGM 1416-B Electricity-only E7 meter; Chameleon IHD3-PPMID-AAA | It may look as if I know what I’m talking about, but don’t let that fool you. |
Tron Burgundy
Rank 4
Rank 4
March 14, 2024

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.

Firedog
Super User
Super User
March 14, 2024

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 (mozilla.org)

All way over my head, I’m afraid.

 

Noel | I have no official status; I'm just a volunteer who comes here to help other customers. My gear: Aclara SGM 1416-B Electricity-only E7 meter; Chameleon IHD3-PPMID-AAA | It may look as if I know what I’m talking about, but don’t let that fool you. |
Tron Burgundy
Rank 4
Rank 4
March 15, 2024

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.

Tron Burgundy
Rank 4
Rank 4
April 3, 2024

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.

Newcomer
April 3, 2024

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.]

Chris_OVO
Community Manager
Community Manager
April 3, 2024

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 🙂

Renewable energy jokes never get old.
Tron Burgundy
Rank 4
Rank 4
April 3, 2024

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:

 

 

Thanks.

Newcomer
April 3, 2024

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:

 

 

Thanks.

I did that. But that link isn’t taking me to the smartapi site, it’s going to https://account.ovoenergy.com/