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+=edhhh].consumption,d2d=new Date(ednhh].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)} 0${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=acctt"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=t],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%20E%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(),bhtzone].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> 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+=edghh].consumption;
d2d = new Date(edthh].interval.start);
tsh = d2d.getHours();
if (d2d.getTimezoneOffset() != 0) tsh++;
if (tsh >= 16 && tsh < 19)
e427Tot+=edlhh].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)} A${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 = acctc"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?'◉':"◎";
}