From 0425af9e5a0e6e56ccdcaa874537608528b84e34 Mon Sep 17 00:00:00 2001 From: Alin Balutoiu Date: Fri, 22 Mar 2024 23:11:03 +0000 Subject: [PATCH] Add dynamic limits --- README.md | 31 +++++++++++++++++++++-- octopus-energy-rates-card.js | 48 +++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e541a03..6ddeb5a 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ Here's a breakdown of all the available configuration items: | showpast | Y | false | Show the rates that have already happened today. Provides a simpler card when there are two days of dates to show | | showday | Y | false | Shows the (short) day of the week next to the time for each rate. Helpful if it's not clear which day is which if you have a lot of rates to display | | title | Y | "Agile Rates" | The title of the card in the dashboard | -| lowlimit | Y | 5 (pence) | If the price is above `lowlimit`, the row is marked dark green. (this option is only applicable for import rates | +| lowlimit | Y | 5 (pence) | If the price is above `lowlimit`, the row is marked dark green. (this option is only applicable for import rates) | | mediumlimit | Y | 20 (pence) | If the price is above `mediumlimit`, the row is marked yellow | | highlimit | Y | 30 (pence) | If the price is above `highlimit`, the row is marked red. | | limitEntity | Y | N/A | Name of the sensor tracking the unit rate to be used to calculate limits. e.g. average rate for the last 12 hours If this is set, MediumLimit and HighLimit are ignored| @@ -108,6 +108,7 @@ Here's a breakdown of all the available configuration items: | multiplier | Y | 100 | multiple rate values for pence (100) or pounds (1) | | rateListLimit | Y | N/A | Limit number of rates to display, useful if you only want to only show next 4 rates | | cardRefreshIntervalSeconds | Y | 60 | How often the card should refresh to avoid using lots of CPU, defaults to once a minute | +| additionalDynamicLimits | Y | N/A | List of additional limits to be displayed in the card. This is very similar to `targetTimesEntities` but it supports entities that have a single value state (for example an input number or a sensor). The color specified here takes precedence compared to the one in `targetTimesEntities`. | #### A note on colouring @@ -120,6 +121,28 @@ Here's a breakdown of all the available configuration items: * Cheapest rate is coloured in light green (above 0) / light blue (below 0) * If targetTimesEntities is included in the config, the target hours will be highlighted in Navy by default (can be changed via the config) +#### A note on `lowlimit` and `mediumlimit` and `highlimit` options + +You can either set these to a fixed value, or you can specify the entity which contains the value you want to use for these limits. + +An example of how the fixed values look in the config: + +```yaml +lowlimit: 15 +mediumlimit: 20 +highlimit: 30 +``` + +And here's an example of how to use entities for the limits: + +```yaml +lowlimit: sensor.average_rate_last_12_hours +mediumlimit: input_number.medium_rate_limit +highlimit: 30 +``` + +Note that it is possible for you to mix and match fixed values and entities as you see fit. + #### Screenshots ![screenshot_1](assets/import.png) ![screenshot_2](assets/export.png) @@ -147,7 +170,7 @@ multiplier: 100 ``` ![screenshot_3](assets/import_with_target.png) -Here is an example on how you can make use of the `targetTimesEntities` property to highlight the target hours in the card. +Here is an example on how you can make use of the `targetTimesEntities` property to highlight the target hours in the card. It also contains an example for `additionalDynamicLimits` property to highlight when a specific threshold is reached. ``` type: custom:octopus-energy-rates-card pastEntity: event.octopus_energy_electricity_22l4132637_1900026354329_previous_day_rates @@ -165,6 +188,10 @@ hour12: true cheapest: false multiplier: 100 exportrates: false +additionalDynamicLimits: + input_number.threshold_turn_on_air_conditioning: + backgroundColour: DarkOliveGreen + prefix: 💰 targetTimesEntities: binary_sensor.octopus_energy_target_intermittent_best_2h_rates: backgroundColour: orange diff --git a/octopus-energy-rates-card.js b/octopus-energy-rates-card.js index 12af202..8547d7c 100644 --- a/octopus-energy-rates-card.js +++ b/octopus-energy-rates-card.js @@ -167,9 +167,22 @@ class OctopusEnergyRatesCard extends HTMLElement { } } - const lowlimit = config.lowlimit; + var lowlimit = config.lowlimit; var mediumlimit = config.mediumlimit; var highlimit = config.highlimit; + + // Check if we've received a number, if not, assume they are entities + // and read them from the state + if (isNaN(lowlimit)) { + lowlimit = parseFloat(hass.states[lowlimit].state) + } + if (isNaN(mediumlimit)) { + mediumlimit = parseFloat(hass.states[mediumlimit].state) + } + if (isNaN(highlimit)) { + highlimit = parseFloat(hass.states[highlimit].state) + } + const unitstr = config.unitstr; const roundUnits = config.roundUnits; const showpast = config.showpast; @@ -194,6 +207,27 @@ class OctopusEnergyRatesCard extends HTMLElement { const limitHighMult = config.highLimitMultiplier; const limitMedMult = config.mediumLimitMultiplier; + // Create an empty array to store the parsed attributes + var additionalDynamicLimits = []; + const additionalDynamicLimitsEntities = config.additionalDynamicLimits && Object.keys(config.additionalDynamicLimits) || []; + // Iterate through each entity in additionalDynamicLimitsEntities + for (const entityId of additionalDynamicLimitsEntities) { + const limitExtraData = config.additionalDynamicLimits[entityId] || []; + const backgroundColour = limitExtraData.backgroundColour || ""; + const timePrefix = limitExtraData.prefix || ""; + + const limit = parseFloat(hass.states[entityId].state); + if (!isNaN(limit)) { + additionalDynamicLimits.push({ + limit: limit, + color: backgroundColour, + timePrefix: timePrefix, + }) + } else { + console.warn("Couldn't parse entity state ${entityId} as a float") + } + } + if (!(limitEntity == null)) { const limitAve = parseFloat(limitEntityState.state); mediumlimit = limitAve * limitMedMult; @@ -317,6 +351,15 @@ class OctopusEnergyRatesCard extends HTMLElement { targetTimePrefix = targetTime.timePrefix ? targetTimePrefix + targetTime.timePrefix : targetTimePrefix; } }); + // Check if we've got any variable limits defined which will take precedence + additionalDynamicLimits.forEach(function (targetLimit) { + if (key.value_inc_vat <= targetLimit.limit) { + isTargetTime = true; + targetTimeBackgroundColor = "' style='background-color: " + targetLimit.color + ";"; + targetTimePrefix = targetLimit.timePrefix ? targetTimePrefix + targetLimit.timePrefix : targetTimePrefix; + } + }); + // Add the extra space at the end of the prefix if it's not empty targetTimePrefix = targetTimePrefix ? targetTimePrefix + " " : targetTimePrefix; var isCurrentTime = false; @@ -388,6 +431,9 @@ class OctopusEnergyRatesCard extends HTMLElement { const defaultConfig = { targetTimesEntities: null, + // Additional limits specified in a similar format as targetTimesEntities + // but they take input_numbers as input + additionalDynamicLimits: null, // Controls how many columns the rates split in to cols: 1, // Show rates that already happened in the card