/** * Javascript module for waterheater helper methods. * * Copyright (c) 2022 Markus Sipilä. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /** * Exports. */ module.exports = { determineHours: determineHours }; /** * Calculates the on/off hours for the waterheater.. * * @param Date start * Start of the time range where to find the cheap hours. * @param Date stop * Stop of the time range where to find the cheap hours. * @param int num * Number of hours the waterheater must be on. * * @return array * Array of point objects. */ function determineHours(start, stop, num) { console.log('waterheater.js: Starting to calculate on/off hours for the waterheater...' + num); const prices = influx.getPrices(start, stop); const startIndex = findStartIndex(prices, num); const points = preparePoints(prices, startIndex, num); return points; } /** * Finds the cheapester hours for the waterheater. * * The power must be on for 'num' hours in a row so that the waterheater * can reach it's max temperature. Reaching the max tempereature is important * to avoid legionella bacteria. * * @param array prices * Array of point objects containing prices for each hour. * @param int num * Number of hours the waterheater must be on. * * @return int * Index of 'prices' array when the heating shoud start. */ function findStartIndex(prices, num) { let cheapestSum = 0; let cheapestIndex = 0; for (let i = 0; i <= prices.length - num; i++) { let sum = 0; // Calculate the sum of the hourly prices for the current 'num' hours. for (let j = i; j < i + num; j++) { let point = prices[j]; sum += point.value; } // Initial value for the cheapestSum. if (i == 0) { cheapestSum = sum; } if (sum < cheapestSum) { cheapestSum = sum; cheapestIndex = i; } } console.debug('waterheater.js: Cheapest index: ' + cheapestIndex + ', sum: ' + cheapestSum); return cheapestIndex; } /** * Prepares the control points to be written to the database. * * @param array prices * Array of point objects. * @param int startIndex * Index of the 'prices' array when heating shoud start. * @param int num * Number of hours the waterheater must be on. * * @return array * Array of point objects. */ function preparePoints(prices, startIndex, num) { let points = []; for (let i = 0; i < prices.length; i++) { let value = 0; if ((i >= startIndex) && (i < startIndex + num)) { value = 1; } let point = { datetime: prices[i].datetime, value: value } points.push(point); } return points; }