Zonnepanelen prognose script voor de Solar Edge omvormer op basis minuten daglicht + historie

Script geschreven voor een SolarEdge omvormer. Onderstaande script maakt twee Logic Tags aan, genoemd Solar TextBlock 1 en Solar TextBlock 2 met de prognose gegevens van de dag, de maand, het jaar en de historische productie. Je kunt deze tags gebruiken in bijv. een email. Handig is dat je al een maandelijkse prognose hebt voor jou zonnepanelen en eventueel de historische productie. Nadat deze gegevens zijn gevuld wordt de data automatisch binnengehaald en bijgewerkt.

Pas het script aan met jou gegevens tot en met const longitude.

Iedere 1e van de maand wordt de nieuwe maandprognose op basis van het aantal daglichtminuten automatisch opgehaald. De eerste keer kan je in het script bij maualUpdate true invullen, zodat deze gegevens direct worden binnengehaald. Vergeet daarna niet weer op false te zetten, anders haalt het script iedere dag deze gegevens binnen en zal je vermoedelijk te veel api calls doen bij de site sunrise sunset.

Output zie er afhankelijk van je email programma prima/redelijk uit. In mijn geval op een iphone is de output helaas soms een beetje verschoven. Interesseert jou de historie niet, dan zet je Solar TextBlock 2 niet in je flow.

//fill in yourself these variables
const manualUpdate = false;//Fill in true if you want to retrieve the data for the daylight prognosis
const id = 'XXXXXXX';//Fill in between ' ' the Id of your SolarEdge
const apiKey = 'XXXXXXXXXXXXXXX';// Fill in between ' 'your Solaredge Api key
const installYear = XXXX //Fill in installation year of your Solar Panels
const installMonth = X;//Fill in installation month of your Solar Panels
const installDay = XX;//Fill in installation day of your Solar Panels
var monthProg = [XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX];//Fill in your monthprognonis
var monthProduction = [0,0,0,0,0,0,XXX,XXX,XXX,XXX,XXX,XXX,XXX,XXX]; //Fill in your historical production, always start with january, even if there was a zero production, last month doesn't have to be december
const latitude = XX.XXXXXX;//Fill in latitude in decimal degrees South add a '-' in front of the degrees
const longitude = -X.XXXXXX;//Fill in longitude in decimal degrees, For East add a '-' in front of the degrees


function getDaysInMonth(year, month) {
return new Date(year, month, 0).getDate();}

function toMonthName(monthNumber) {
const date = new Date();
date.setMonth(monthNumber);
return date.toLocaleString('en-US', 
{month: 'long',});}

const date = new Date();
const currentYear = date.getFullYear();
const currentMonth = date.getMonth() + 1;
const currentMonthTwoDigits = ("0" +currentMonth).slice(-2);
const daysInCurrentMonth = getDaysInMonth(currentYear, currentMonth);
const currentDay = new Date().getDate();
const currentDayTwoDigits = ("0" +currentDay).slice(-2);
const installMonthTwoDigits = ("0" +installMonth).slice(-2);
const installDayTwoDigits = ("0" +installDay).slice(-2);
const degeneration = 0.004;


//Setting Prognosis
global.set('monthProg', monthProg);
var monthProg = global.get('monthProg');
var yearProg = monthProg.reduce((partialSum, a) => partialSum + a, 0); 
yearProg = yearProg.toFixed(0);
console.log('yearProg is: ' +yearProg +' kWh');

//Setting degeneration
var degenerationYears = currentYear - installYear;
var degenerationPercentage = degenerationYears * degeneration;
  console.log('degenerationPercentage is: '+degenerationYears +' * '+degeneration +'= ' +degenerationPercentage +' %');
monthProgDegenerated = monthProg.map(x => x - (x * degenerationPercentage));//
global.set('monthProgDegenerated', monthProgDegenerated);
var yearProgDegenerated = (yearProg - (yearProg * degenerationPercentage));
      console.log('Prognosis this year minus a DegenerationPercentage of: ' +degenerationPercentage +'% Prognosis is: '+yearProgDegenerated +' kWh');
console.log('monthProgDegenerated is :' +monthProgDegenerated);
console.log('yearProgDegenerated is :' +yearProgDegenerated);


//Setting Production
global.set('monthProduction', monthProduction);
var yearProduction = [];
monthProduction = global.get('monthProduction');

var count = 0;
while (count <= (currentYear - installYear)){
var temp = monthProduction.slice(0 + (count * 12),12 + (count * 12)).reduce((a, b) => a + b,0);
yearProduction.splice(count,1,temp);
  console.log('yearProduction is:' +yearProduction);
count++}
global.set('yearProduction', yearProduction);
yearProduction = global.get('yearProduction');

let res = await fetch('https://monitoringapi.solaredge.com/site/'+id+'/energyDetails.json?&timeUnit=MONTH&startTime='+currentYear +'-01-01%2000:00:00&endTime='+currentYear +'-' +currentMonthTwoDigits +'-' +currentDayTwoDigits +'%2023:59:59&api_key='+apiKey);//Get the request for this year monthly production

if (!res.ok) {
  throw new Error(res.statusText);}

var body = await res.json();
count = 0;
monthProduction = global.get('monthProduction');
  console.log('monthProduction is: ' +monthProduction);
var arrayPositionProduction = 0 + ((currentYear - installYear) * 12);

while (count <= currentMonth - 1){
monthProduction = monthProduction.map(function(each_element){
   return Number(each_element.toFixed(0));
});

  console.log('monthProduction is: ' +monthProduction);
monthProduction.splice((arrayPositionProduction +count), 1, Math.round(((body.energyDetails.meters[0].values[count].value)/1000)));
  console.log('arrayPositionProduction + teller is: '+(arrayPositionProduction +count)); 
count++;}

global.set('monthProduction', monthProduction);
monthProduction = global.get('monthProduction');
  console.log('monthProduction is: '+monthProduction);

let res2 = await fetch('https://monitoringapi.solaredge.com/site/'+id +'/overview.json?api_key='+apiKey);
if (!res2.ok) {
  throw new Error(res2.statusText);}
var body2 = await res2.json();//Get the body JSON

var lifeTimeProductionUntilToday = Math.round((body2.overview.lifeTimeData.energy)/1000);
var yearProductionUntilToday = Math.round((body2.overview.lastYearData.energy)/1000);
var monthProductionUntilToday =  Math.round(((body2.overview.lastMonthData.energy)/1000));
var dayProductionUntilToday = ((body2.overview.lastDayData.energy)/1000).toFixed(2);
var dayLightMonth =  global.get('dayLightMonth');
monthUpdate = global.get('monthUpdate')

//Setting daylight minutes for a month
if (currentMonth === monthUpdate || manualUpdate === true)
{
const process = this.constructor.constructor('return process')();
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
//the api call is from a unsecured website, therefore a workaround

global.set('dayLightMonth', []);
dayLightMonth = [];
count = 1;
while(count <= daysInCurrentMonth){
    console.log('count is: ' +('0'+count).slice(-2)) 
url = ('https://api.sunrise-sunset.org/json?lat='+latitude +'&lng='+longitude +'&date=' + currentYear + '-' + currentMonth + '-' +count +'&formatted=0');
response = await fetch(url);
apiSunriseSunset = await response.json();
dayLightMonth.splice(count -1,1,apiSunriseSunset.results.day_length);
count++;
}

dayLightMonth = global.set('dayLightMonth', dayLightMonth)

if (currentMonth + 1 === 13){
var currentMonthCorrected = 0;
var currentYearCorrected = (currentYear + 1);
}
else{
var currentMonthCorrected = currentMonth + 1;}
global.set('monthUpdate', currentMonthCorrected);
monthUpdate = global.get('monthUpdate');
  console.log('currentmonth is '+currentMonth +' currentMonthCorrected is ' +monthUpdate +' these two months have to be different, are they equal, an monthupdate will start');
}

var dayLightMonth =  global.get('dayLightMonth');
    console.log('dayLightMonth is :'+dayLightMonth);
var dayLightMonthTotalMinutes = dayLightMonth.slice(0,daysInCurrentMonth).reduce((a, b) => a + b,0)
    console.log('Total dayLightMonthTotalMinutes = '   +dayLightMonthTotalMinutes);

if (currentYear > installYear)
{
var dayLightMonthTotalMinutesPast = dayLightMonth.slice(0,currentDay).reduce((a,b)=>a+b,0) ;
    console.log('Total daylight minutes from the first of the month until the current day: '+dayLightMonthTotalMinutesPast)
var dayLightMonthTotalMinutesFuture = dayLightMonth.slice(currentDay,daysInCurrentMonth).reduce((a,b)=>a+b,0) ;
    console.log('Total daylight minutes from the currentday intil the end of the month of: '+dayLightMonthTotalMinutesFuture)
var dayProgUntilToday = (((monthProgDegenerated[currentMonth - 1]/ dayLightMonthTotalMinutes) * dayLightMonth[currentDay-1])).toFixed(2);
  console.log('dayProgUntilToday is: ' +dayProgUntilToday);
var dayProgUntilTodayWithoutDegeneration = (((monthProg[currentMonth - 1]/ dayLightMonthTotalMinutes) * dayLightMonth[currentDay-1])).toFixed(2);
  console.log('dayProgUntilTodayWithoutDegeneration is: ' +dayProgUntilTodayWithoutDegeneration);
var monthProgUntilToday = ((monthProgDegenerated[currentMonth - 1]/ dayLightMonthTotalMinutes) * dayLightMonthTotalMinutesPast);
  console.log('monthProgUntilToday is: ' +monthProgUntilToday);
var monthProgUntilTodayWithoutDegeneration = ((monthProg[currentMonth - 1]/ dayLightMonthTotalMinutes) * dayLightMonthTotalMinutesPast);
  console.log('monthProgUntilTodayWithoutDegeneration is: ' +monthProgUntilTodayWithoutDegeneration);
var yearProgUntilToday = (monthProgDegenerated.slice(0,currentMonth -1).reduce((a,b)=>a+b,0)) + monthProgUntilToday;
  console.log('yearProgUntilToday is: ' +yearProgUntilToday)
var yearProgUntilTodayWithoutDegeneration = (monthProg.slice(0,currentMonth -1).reduce((a,b)=>a+b,0)) + monthProgUntilTodayWithoutDegeneration;
  console.log('yearProgUntilTodayWithoutDegeneration is: ' +yearProgUntilTodayWithoutDegeneration)
}
else
{
var dayLightMonthTotalMinutesPast = dayLightMonth.slice(installDay -1,currentDay).reduce((a,b)=>a+b,0);
    console.log('Total daylight minutes from the first of the month until the instal day: '+dayLightMonthTotalMinutesPast)
var dayLightMonthTotalMinutesFuture = dayLightMonth.slice(currentDay,daysInCurrentMonth).reduce((a,b)=>a+b,0);
    console.log('Total daylight minutes from the currentday intil the end of the month: '+dayLightMonthTotalMinutesFuture)
var dayProgUntilToday = ((((monthProgDegenerated[currentMonth - 1]/ dayLightMonthTotalMinutes) * dayLightMonth[currentDay-1]))).toFixed(2);
  console.log('dayProgUntilToday is: ' +dayProgUntilToday);
var monthProgUntilToday = ((monthProgDegenerated[currentMonth - 1]/ (dayLightMonthTotalMinutesPast + dayLightMonthTotalMinutesFuture) * dayLightMonthTotalMinutesPast));
  console.log('monthProgUntilToday is: ' +monthProgUntilToday);
var yearProgUntilToday = (monthProgDegenerated.slice(0,(instalMonth -1)).reduce((a,b)=>a+b,0)) + monthProgUntilToday;
  console.log('yearProgUntilToday is: ' +yearProgUntilToday)
}

var yearDifference = (yearProductionUntilToday- yearProgDegenerated);//Calculating differences between the degenerated prognosis and realized production
      console.log('Difference between the Degenerated Year prognosis and total production '+yearDifference);
var yearDifferenceUntilToday = (yearProgDegenerated - yearProductionUntilToday);
      console.log('Difference between the Year prognosis untill today and production including todays production untill now: '+yearDifferenceUntilToday);
      console.log('yearProgUntilToday is: '+yearProgUntilToday);
var monthDifference = (monthProduction[(currentMonth - 1) + ((currentYear - installYear) * 12)] - monthProgDegenerated[currentMonth -1]);
      console.log('Difference between the Month prognosis and production including todays production untill now '+monthDifference);
var monthDifferenceUntilToday = (monthProduction[(currentMonth - 1) + (currentYear - installYear) * 12] - monthProgUntilToday);
      console.log('Difference between the Month prognosis untill today and production including todays production untill now '+monthDifferenceUntilToday);
var dayDifference = (dayProductionUntilToday - dayProgUntilToday).toFixed(2);
      console.log('Difference between the Day prognosis and production including todays production untill now: '+dayDifference);


var progRealizedExact = 'De prognose is precies gehaald.';
var yearProgRealized =  'De prognose is gehaald, het overschot dit jaar is: ' +Math.round(yearDifference) + 'kWh.';
var yearProgNotRealized = 'Er moet nog ' +Math.round(yearDifference * -1) +' kWh' +' worden geproduceerd om de prognose te halen.';
var monthProgRealized = 'De prognose is gehaald, overschot is: ' +Math.round(monthDifference) +' ' +' kWh.';
var monthProgNotRealized = 'Er moet nog ' +Math.round(monthDifference * -1) +' kWh' +' worden geproduceerd om de prognose te halen.';
var dayProgRealized =  'De prognose is gehaald, het overschot vandaag is: '+dayDifference +' kWh.';
var dayProgNotRealized = 'Er moet nog ' +dayDifference +' kWh' + ' worden geproduceerd om de prognose te halen.';
var apostrophe = "'";

if (yearDifference == 0){
var yearTxt = progRealizedExact
      console.log('Text year prognosis exactly realized: ' +yearTxt);}
else if
(yearDifference < 0) {
var yearTxt = yearProgNotRealized
      console.log('Text year prognosis not realized: ' +yearTxt);}
else if (yearDifference > 0 ) {
var yearTxt = yearProgRealized
      console.log('Text year prognosis realized: ' +yearTxt);}

if (monthDifference == 0){
var monthTxt = progRealizedExact
      console.log('Text month prognosis exactly realized: ' +monthTxt);}
else if (monthDifference < 0) {
var monthTxt = monthProgNotRealized
      console.log('Text month prognosis not realized : ' +monthTxt);}

else if (monthDifference > 0 ) {
var monthTxt = monthProgRealized
      console.log('Text month prognosis realized: ' +monthTxt);}

if (dayDifference == 0){
dayTxt = progRealizedExact
      console.log('Text day prognosis exactly realized: ' +dayTxt);}
else if (dayDifference < 0) {
dayTxt = dayProgNotRealized
      console.log('Text day prognosis not realized: ' +dayTxt);}
else if (dayDifference > 0 ) {
dayTxt = dayProgRealized
      console.log('Text day prognosis realized: ' +dayTxt);}

//Making the Logic textblock
var solarTextBlock1 = 'Dagproductie: ' +dayProductionUntilToday +' kWh.' +' De prognose is: '+dayProgUntilToday +' kWh, verschil => ' +dayDifference +' kWh.' + ' De prognose zonder degeneratie is: '+dayProgUntilTodayWithoutDegeneration +' kWh.' + '\r\n' + '\r\n'
+'Maandproductie: ' +Math.round(monthProductionUntilToday)  +' kWh.' +' De prognose tot vandaag is ' +Math.round(monthProgUntilToday) +' kWh, verschil => '+Math.round(monthProductionUntilToday - monthProgUntilToday) +' kWh.' +' De prognose zonder degeneratie is: '+ Math.round(monthProgUntilTodayWithoutDegeneration) +' kWh.' + '\r\n' + '\r\n'
+'Maandprognose: ' +Math.round(monthProgDegenerated[currentMonth - 1]) +' kWh. ' +monthTxt +' De prognose zonder degeneratie is: '+Math.round(monthProg[currentMonth - 1]) + ' kWh.'+ '\r\n' + '\r\n'
+'Jaarproductie: ' +Math.round(yearProductionUntilToday) +' kWh.' +' De prognose tot vandaag is ' +Math.round(yearProgUntilToday) +' kWh, verschil => ' +Math.round(yearProductionUntilToday - yearProgUntilToday) + ' kWh.' +' De prognose zonder degeneratie is: ' + Math.round(yearProgUntilTodayWithoutDegeneration) + ' kWh.' + '\r\n' + '\r\n'
+' Jaarprognose: ' +Math.round(yearProgDegenerated) +' kWh. ' +yearTxt +' De prognose zonder degeneratie is: '+Math.round(yearProg) + ' kWh.' + '\r\n' + '\r\n'
+'Jaarproductie  ' +installYear +': ' + yearProduction[0] +' kWh.' +'\r\n'
+ 'Jaarproductie  ' +(installYear +1) +':  '+ yearProduction[1]+' kWh.' + '\r\n' + '\r\n'

count = 0;
while(count <= currentYear - installYear){
global.set('productionWithMonthAndYear'+count , []);
count++
}

count = 0
while (count <= currentYear - installYear){
var temp = global.get('monthProduction');
  console.log('monthProduction is: ' +temp)
temp = temp.slice(0 + (count * 12),12 + (count * 12));
global.set('productionWithMonthAndYear' +count , temp);
global.set('monthProductionYear' +count , temp);
  console.log('productionWithMonthAndYear' +count +' = : ' +temp)
  console.log('monthProductionYear' +count +' = : ' +temp)
count++
}

count = 0;
number = 0;
while(count <= currentYear - installYear){
productionWithMonthAndYear = global.get('productionWithMonthAndYear' +number);
productionWithMonthAndYear = productionWithMonthAndYear.map(a => "'" +('' +(installYear + count)).slice(-2) +'(' +a +')');

monthLetters = ['01','02','03','04','05','06','07','08','09','10','11','12'];

var count1 = 0;
var arrayLength = (productionWithMonthAndYear.length -1);
  console.log('array length is: ' +arrayLength);

while(count1 <= arrayLength){
productionWithMonthAndYear.splice(count1,1,'' +monthLetters[count1]  +productionWithMonthAndYear[count1]);
global.set('productionWithMonthAndYear' +number , productionWithMonthAndYear);
console.log(productionWithMonthAndYear)
count1++
}
count++
number++
}

count = 0
var temporarily = new Array();
monthProduction = global.get('monthProduction');

while(count <= (currentYear - installYear) -1 ){
var arrayIndex = 0
var productionYearFirst = global.get('monthProductionYear'+count);
  console.log('productionYearFirst is: ' +productionYearFirst);
var productionYearSecond = global.get('monthProductionYear'+(count + 1));
  console.log('productionYearSecond is: ' +productionYearSecond);
var productionWithMonthAndYearFirst = global.get('productionWithMonthAndYear' +count);
var productionWithMonthAndYearSecond = global.get('productionWithMonthAndYear' +(count + 1));

while(arrayIndex <= (productionWithMonthAndYearSecond.length) - 1 ){
if (count  <= currentYear - installYear){
temporarily.push(''+productionWithMonthAndYearFirst[arrayIndex] +' kWh' +'\t' +'\t' +productionWithMonthAndYearSecond[arrayIndex] +' kWh(' +Math.round((productionYearSecond[arrayIndex] - productionYearFirst[arrayIndex])) +')' + '\r\n')
arrayIndex++
}
else{
temporarily.push(''+productionWithMonthAndYearSecond[arrayIndex] +' kWh'  + '\r\n')
arrayIndex++  
}
}
count++;
}
temporarily = ''+temporarily.join('\'')
  console.log(''+temporarily)

var solarTextBlock2 = ''+temporarily
await tag('Solar TextBlock 1', solarTextBlock1);
await tag('Solar TextBlock 2', solarTextBlock2);

3 Likes