Files
zorruno-noderedappliancemon…/mainloop-function.js
2023-01-26 13:32:30 +13:00

198 lines
6.6 KiB
JavaScript

// -----------------------------------------
// Notify and store power use and cost for an appliance
// MAIN LOOP
// Full loop to calculate power average of appliance and
// work out when it is operating. When operational
// fill arrays with power used, and cost of power calculated.
// -----------------------------------------
// 2021-04-12 V1.3 - zorruno
// - Fixed loop not detecting Finished-> Standby
// - Moved some flow variables to context
// - Changed csv filename to reflect appliance
// -----------------------------------------
// The input message must be the current power in Watts
var power = msg.payload;
// Get flow user settings variables into local variables
var res = flow.get("resolution");
var tariff = flow.get("tariff");
var metricsf = flow.get("metricFrequency");
var standby = flow.get("standbyPower");
var opPowerMin = flow.get("operatingPowerMinium");
var currentCycle = flow.get("currentApplianceCycle");
// Get flow variables into local variables
var operation = context.get("operation") || "Off";
var recentPowerArray = flow.get("recentPowerArray") || [0];
var cycleCostArray = flow.get("cycleCostArray") || [0];
var cyclePowerArray = flow.get("cyclePowerArray") || [0];
// Get date, seconds and hours
var date = new Date();
var dateS = date.getTime()/1000;
var hour = date.getHours();
// -----------------------------------------
// Fill power array, and calculate average
// power. Do this on every loop.
// -----------------------------------------
// Function add for reduce array
function add(accumulator, a) {
return accumulator + a;
}
// Push power into TotalPower array for average
recentPowerArray.unshift(power);
// Remove X element to get total resolution for average calc
if(recentPowerArray[res] === undefined) {
flow.set("recentPowerArray", recentPowerArray);
}
else {
recentPowerArray.splice(res, 1);
flow.set("recentPowerArray", recentPowerArray);
}
// Calculate average power from array
var sum = recentPowerArray;
var average = (sum.reduce(add)/recentPowerArray.length); // Average the array
// -----------------------------------------
// Fill cycle power array, and calculate average power.
// Only do this when cycle is occurring.
// Note this method doesn't capture EVERY data point -
// we'll miss the first few as we are calculating an
// average. We could capture more, but that is less efficient.
// -----------------------------------------
if(operation === "Operating"){
// Push watthours into cyclePowerArray for cycle
var wattHoursNow = power / ( 60 * ( 60 / metricsf ));
cyclePowerArray.push(wattHoursNow);
flow.set("cyclePowerArray", cyclePowerArray);
// Calculate the cost of power
var price;
if( hour >= tariff.start && hour < tariff.end ){
price = tariff.costDay; // Apply day tariff
}
if( hour < tariff.start || hour >= tariff.end ){
price = tariff.costNight; // Apply night tariff
}
// Fill cycleCostArray
var costPerMinute = power/1000 * price / (60* (60/metricsf));
cycleCostArray.push(costPerMinute);
flow.set("cycleCostArray", cycleCostArray); // Add to cost array
}
// -----------------------------------------
// Appliance is off
// -----------------------------------------
//if(average === 0){
if(average < standby){
context.set("operation", "Off");
}
// -----------------------------------------
// Appliance has gone into Standby from Off
// -----------------------------------------
if(average >= standby && operation === "Off"){
context.set("operation", "Standby");
}
// -----------------------------------------
// Appliance has gone into Standby from Finished
// -----------------------------------------
if(average >= standby && operation === "Finished"){
context.set("operation", "Standby");
}
// -----------------------------------------
// Appliance has started its Operating cycle
// from Standby or Off
// -----------------------------------------
if((average > opPowerMin && operation === "Standby") || (average > opPowerMin && operation === "Off")){
context.set("operation", "Operating");
currentCycle.cycleTimeStart = dateS;
cycleCostArray = [0]; // Clear array to start cycle
flow.set("cycleCostArray",cycleCostArray);
cyclePowerArray = [0]; // Clear array to start cycle
flow.set("cyclePowerArray",cyclePowerArray);
}
// -----------------------------------------
// Appliance was in Operating cycle,
// but now has Finished
// -----------------------------------------
if(average < opPowerMin && operation === "Operating"){
context.set("operation", "Finished");
currentCycle.cycleTimeStop = dateS;
// Calculate & format total cost of the entire cycle
var sumCost = flow.get("cycleCostArray");
var costOfPower = sumCost.reduce(add);
currentCycle.totalCycleCostDollars = costOfPower;
// Format as $ or cents
if ( costOfPower < 0.01 ){
costOfPower = '<1c';
} else if ( costOfPower < 1){
costOfPower = costOfPower * 100;
costOfPower = Math.round(costOfPower);
costOfPower = costOfPower.toString() + 'c';
} else {
costOfPower = costOfPower.toFixed(2);
costOfPower = '$' + costOfPower.toString();
}
currentCycle.totalCycleCostFormatted = costOfPower ;
// Calculate & format total power use of the entire cycle
var sumPower = flow.get("cyclePowerArray");
var sumOfPower = sumPower.reduce(add);
currentCycle.totalCyclePowerWattHours = sumOfPower;
// Format as wH or kWh
if ( sumOfPower >= 1000 ){
sumOfPower = sumOfPower / 1000;
sumOfPower = sumOfPower.toFixed(1); // 1 decimal place
sumOfPower = sumOfPower.toString() + 'kWh';
} else if ( costOfPower < 1){
costOfPower = '<1Wh';
} else {
sumOfPower = sumOfPower.toFixed(1); // 1 decimal place
sumOfPower = sumOfPower.toString() + 'Wh';
}
currentCycle.totalCyclePowerFormatted = sumOfPower ;
msg.payload = context.get("operation") ;
return [msg,msg]
}
// -----------------------------------------
// Output debug stuff on each loop
// -----------------------------------------
if(flow.get("debugFlow") === true){
flow.set("debugAverage",average) ;
// Calculate total cost of the entire cycle so far
var costSoFar = flow.get("cycleCostArray").reduce(add);
flow.set("debugCostSoFar",costSoFar) ;
// Calculate total power use of the entire cycle so far
var powerSoFar = flow.get("cyclePowerArray").reduce(add);
flow.set("debugPowerSoFar",powerSoFar) ;
flow.set("debugCyclePowerArray",cyclePowerArray) ;
flow.set("debugCycleCostArray",cycleCostArray) ;
flow.set("debugRecentPowerArray",recentPowerArray) ;
msg.payload = context.get("operation") ;
return [null,msg]
}