198 lines
6.6 KiB
JavaScript
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]
|
|
}
|
|
|
|
|
|
|