From da4814f091647f9d775110edecca466b65127b18 Mon Sep 17 00:00:00 2001
From: mentalilll <159670055+mentalilll@users.noreply.github.com>
Date: Wed, 21 Feb 2024 00:09:10 +0100
Subject: [PATCH] Update ha-vpd-chart.js
Added huge Performance boost,
Added bar view
---
ha-vpd-chart.js | 539 +++++++++++++++++++++++++++++++++---------------
1 file changed, 375 insertions(+), 164 deletions(-)
diff --git a/ha-vpd-chart.js b/ha-vpd-chart.js
index 2cac1cf..315199d 100644
--- a/ha-vpd-chart.js
+++ b/ha-vpd-chart.js
@@ -11,9 +11,11 @@ class HaVpdChart extends HTMLElement {
vpd_phases: {type: Array},
air_text: {type: String},
rh_text: {type: String},
- enable_tooltip: {type: Boolean}
+ enable_tooltip: {type: Boolean},
+ is_bar_view: {type: Boolean}
};
}
+
constructor() {
super();
this.vpd_phases = [
@@ -25,6 +27,7 @@ class HaVpdChart extends HTMLElement {
];
this.vpdCache = new Map();
this.sensors = [];
+ this.is_bar_view = false;
this.min_temperature = 5;
this.max_temperature = 35;
this.min_humidity = 10;
@@ -39,139 +42,360 @@ class HaVpdChart extends HTMLElement {
// Whenever the state changes, a new `hass` object is set. Use this to
// update your content.
set hass(hass) {
+ if (this.is_bar_view === false) {
+ this.buildChart(hass);
+ } else {
+ this.buildBarChart(hass);
+ }
+ }
+
+ setConfig(config) {
+ this.config = config;
+ if (!config.sensors) {
+ throw new Error('You need to define sensors');
+ }
+
+ this.vpd_phases = config.vpd_phases || this.vpd_phases;
+ this.sensors = config.sensors || this.sensors;
+ this.airText = config.air_text || "Air";
+ this.rhText = config.rh_text || "RH";
+ this.min_temperature = config.min_temperature || this.min_temperature;
+ this.max_temperature = config.max_temperature || this.max_temperature;
+ this.min_humidity = config.min_humidity || this.min_humidity;
+ this.max_humidity = config.max_humidity || this.max_humidity;
+ this.steps_temperature = config.steps_temperature || this.steps_temperature;
+ this.steps_humidity = config.steps_humidity || this.steps_humidity;
+ this.is_bar_view = config.is_bar_view || this.is_bar_view;
+ }
+
+ buildBarChart(hass) {
+ if (!this.content) {
+ this.innerHTML = `
+
+
+
+
+
+
+
+
+ Under Transpiration
+
+
+
+ Early Veg
+
+
+
+ Late Veg
+
+
+
+ Mid Late Flower
+
+
+
+ Danger Zone
+
+
+
+
+
+ `;
+ this.content = this.querySelector("div.vpd-card-container");
+ }
+
+ let container = document.createElement('div');
+
+ this.config.sensors.forEach((sensor, index) => {
+ let humidity = hass.states[sensor.humidity].state;
+ let temperature = hass.states[sensor.temperature].state;
+ let leafTemperature = temperature - 2;
+ if (sensor.leaf_temperature !== undefined) {
+ leafTemperature = hass.states[sensor.leaf_temperature].state;
+ }
+ let vpd = sensor.vpd || this.calculateVPD(parseFloat(leafTemperature), parseFloat(temperature), parseFloat(humidity)).toFixed(2)
+ let card = document.createElement('ha-card');
+ card.innerHTML += `
+
+ ${sensor.name}
+ ${vpd} kPa
+ ${this.rhText}: ${humidity}%
+ ${this.airText}: ${temperature}°C
+
+
+ `;
+ container.appendChild(card);
+ if (this.enable_tooltip) {
+ this.content.addEventListener('mouseover', (event) => {
+ if (event.target.classList.contains('tooltip')) {
+ this.buildMouseTooltip(event.target, hass);
+ }
+ });
+ this.addEventListener('mouseleave', (event) => {
+ let tooltip = this.querySelector('.mousePointer');
+ let fadeOut = setInterval(function () {
+ if (!tooltip.style.opacity) {
+ tooltip.style.opacity = 1;
+ }
+ if (tooltip.style.opacity > 0) {
+ tooltip.style.opacity -= 0.1;
+ } else {
+ clearInterval(fadeOut);
+ }
+ }, 100);
+ });
+ } else {
+ this.querySelector('.mousePointer').style.display = 'none';
+ }
+ });
+ this.content.replaceChildren(container);
+ }
+
+ buildChart(hass) {
// Initialize the content if it's not there yet.
if (!this.content) {
this.innerHTML = `
-
-
+
+
+
- margin-bottom: 5px;
- /*margin-left: -120px;*/
- margin-left: -5px;
- padding: 7px;
- width: 240px;
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- border-radius: 3px;
- background-color: #000000;
- background-color: hsla(0, 0%, 20%, 0.9);
- color: #ffffff;
-
- text-align: center;
- font-size: 12px;
- line-height: 1.2;
- position: absolute;
- }
-
- .custom-tooltip:after {
-
- position: absolute;
- bottom: -15%;
- left: 2%;
-
- width: 0;
- border-top: 5px solid #000000;
- border-top: 5px solid hsla(0, 0%, 20%, 0.9);
- border-right: 5px solid transparent;
- border-left: 5px solid transparent;
- content: " ";
- font-size: 0;
- line-height: 0;
- }
-
- .vpd-table {
- display: table;
- width: 100%;
- height: 100%;
- }
-
- .row {
- display: table-row;
- background-color: #ffffff;
- }
-
- .cell {
- display: table-cell;
- }
-
-
-
-
- `;
+
+ `;
this.content = this.querySelector("div.vpd-card-container");
+
+ let table;
+ if (localStorage.getItem('vpd-table-card')) {
+ table = localStorage.getItem('vpd-table-card');
+ } else {
+ table = this.buildTable();
+ localStorage.setItem('vpd-table-card', table);
+ }
+ this.content.innerHTML = "" + table + "
";
+
}
- let table;
- if (localStorage.getItem('vpd-table-card')) {
- table = localStorage.getItem('vpd-table-card');
- } else {
- table = this.buildTable();
- localStorage.setItem('vpd-table-card', table);
- }
- this.content.innerHTML = "" + table + "
";
this.buildTooltip(this.content, hass);
if (this.enable_tooltip) {
this.content.addEventListener('mouseover', (event) => {
@@ -192,27 +416,10 @@ class HaVpdChart extends HTMLElement {
}
}, 100);
});
- } else {
+ } else {
this.querySelector('.mousePointer').style.display = 'none';
}
}
- setConfig(config) {
- this.config = config;
- if (!config.sensors) {
- throw new Error('You need to define sensors');
- }
-
- this.vpd_phases = config.vpd_phases || this.vpd_phases;
- this.sensors = config.sensors || this.sensors;
- this.airText = config.air_text || "Air";
- this.rhText = config.rh_text || "RH";
- this.min_temperature = config.min_temperature || this.min_temperature;
- this.max_temperature = config.max_temperature || this.max_temperature;
- this.min_humidity = config.min_humidity || this.min_humidity;
- this.max_humidity = config.max_humidity || this.max_humidity;
- this.steps_temperature = config.steps_temperature || this.steps_temperature;
- this.steps_humidity = config.steps_humidity || this.steps_humidity;
- }
getCardSize() {
return 3;
@@ -225,6 +432,7 @@ class HaVpdChart extends HTMLElement {
}
getPhaseClass(vpd) {
+ /* add randomizer for development */
for (const phase of this.vpd_phases) {
if (phase.upper === undefined) {
if (vpd >= phase.lower) {
@@ -279,6 +487,7 @@ class HaVpdChart extends HTMLElement {
buildTooltip(table, hass) {
const fragment = document.createDocumentFragment();
+ const sensors = this.querySelector('#sensors');
this.config.sensors.forEach((sensor, index) => {
let humidity = hass.states[sensor.humidity].state;
let temperature = hass.states[sensor.temperature].state;
@@ -293,47 +502,48 @@ class HaVpdChart extends HTMLElement {
const relativeTemperature = temperature - this.min_temperature;
const totalTemperatureRange = this.max_temperature - this.min_temperature;
const percentageTemperature = (relativeTemperature / totalTemperatureRange) * 100;
+ // Check if the circle already exists, if not create a new one and set a already_created_bool to not append
+ let circle = document.getElementsByClassName('sensor-circle-' + index)[0] || document.createElement('div');
+ circle.className = 'highlight sensor-circle-' + index;
+ circle.style.width = "10px";
+ circle.style.height = "10px";
+ circle.style.backgroundColor = "white";
+ circle.style.borderRadius = "50%";
+ circle.style.position = "absolute";
+ circle.style.left = `${percentageHumidity}%`;
+ circle.style.bottom = `${100 - percentageTemperature}%`;
+ circle.style.transform = "translateX(-50%)";
- const horizontalLine = document.createElement('div');
+ let horizontalLine = document.getElementsByClassName('horizontal-line-' + index)[0] || document.createElement('div');
horizontalLine.style.position = 'absolute';
horizontalLine.style.left = 0;
horizontalLine.style.right = 0;
+ horizontalLine.className = 'horizontal-line horizontal-line-' + index;
horizontalLine.style.top = `calc(${percentageTemperature}% - 5px)`;
horizontalLine.style.height = '1px';
horizontalLine.style.backgroundColor = 'rgba(255,255,255,0.4)';
- this.content.appendChild(horizontalLine);
+ fragment.appendChild(horizontalLine);
- const verticalLine = document.createElement('div');
+ let verticalLine = document.getElementsByClassName('vertical-line-' + index)[0] || document.createElement('div');
verticalLine.style.position = 'absolute';
+ verticalLine.className = 'vertical-line vertical-line-' + index;
verticalLine.style.top = 0;
verticalLine.style.bottom = 0;
verticalLine.style.left = `calc(${percentageHumidity}% - 0.5px)`;
verticalLine.style.width = '1px';
verticalLine.style.backgroundColor = 'rgba(255,255,255,0.4)';
- this.content.appendChild(verticalLine);
+ fragment.appendChild(verticalLine);
- const circle = document.createElement('div');
- circle.className = 'highlight';
- circle.style.width = "10px";
- circle.style.height = "10px";
- circle.style.backgroundColor = "white";
- circle.style.borderRadius = "50%";
- circle.style.position = "absolute";
- circle.style.left = `${percentageHumidity}%`;
- circle.style.bottom = `${100 - percentageTemperature}%`;
- circle.style.transform = "translateX(-50%)";
-
- const tooltip = document.createElement('div');
+ let tooltip = document.createElement('div');
tooltip.className = 'custom-tooltip';
tooltip.innerHTML = `${sensor.name}: kPa: ${vpd} | ${this.rhText}: ${humidity}% | ${this.airText}: ${temperature}°C`;
circle.appendChild(tooltip);
-
fragment.appendChild(circle);
});
requestAnimationFrame(() => {
- table.appendChild(fragment);
+ sensors.replaceChildren(fragment);
});
}
@@ -354,6 +564,7 @@ class HaVpdChart extends HTMLElement {
circle.appendChild(tooltip);
}
}
+
}
customElements.define('ha-vpd-chart', HaVpdChart);