Skip to content

Commit

Permalink
Release 1.3.5
Browse files Browse the repository at this point in the history
feat: added vpd phases to bar chart too
feat: added tooltip to bar chart
feat: added ghostmap settings for explicit time
feat: modified configurator for better handling
feat: added sensors to configurator
feat: added fahrenheit as option
fix: fixed some bar chart bugs
fix: fixed delete last phase bug
fix: some minor bugfixes
  • Loading branch information
mentalilll committed Jun 22, 2024
1 parent 34a096d commit 8e5cef1
Show file tree
Hide file tree
Showing 8 changed files with 604 additions and 340 deletions.
142 changes: 111 additions & 31 deletions dist/bar.css
Original file line number Diff line number Diff line change
@@ -1,82 +1,161 @@
.vpd-bar-view .type-custom-ha-vpd-chart
{
margin-bottom:5px;
.vpd-bar-view .type-custom-ha-vpd-chart {
margin-bottom: 5px;
}

.vpd-bar-view .card-content {
margin:0;
padding-top:16px;
margin: 0;
padding-top: 16px;
}

.vpd-bar-view .bar {
box-shadow: inset 0 0 3em -1.2em rgba(0, 0, 0, 0.5);
padding:15px;
padding: 15px;
border-radius: 5px;
}

.vpd-bar-view .bar span {
border-left:1px solid #999999;
padding-left:5px;
padding-right:5px;
border-left: 1px solid #999999;
padding-left: 5px;
padding-right: 5px;
}

.vpd-bar-view .bar span:first-child {
border-left:0;
padding-left:0;
border-left: 0;
padding-left: 0;
}

.vpd-bar-view .bar span:last-child {
border-left:0;
padding-left:0;
border-left: 0;
padding-left: 0;
}

.vpd-bar-view .vpd-history canvas {
width: 80px;
height:20px;
height: 20px;
}

.vpd-bar-view .legend {
box-shadow: inset 0 0 3em -1.2em rgba(0, 0, 0, 0.5);
padding:15px;
padding: 15px;
}

.vpd-bar-view .vpd-state {
float:right;
width:20px;
height:20px;
padding:0 !important;
border-left:0 !important;
float: right;
width: 20px;
height: 20px;
padding: 0 !important;
border-left: 0 !important;
border-radius: 5px;
position: relative;
}

.vpd-bar-view .vpd-state-legend {
padding:0 !important;
border-left:0 !important;
font-size:11px;
padding: 0 !important;
border-left: 0 !important;
font-size: 11px;
float: left;
display: block;
position: relative;
}

.vpd-bar-view .vpd-state-legend span:first-child {
width:20px;
height:10px;
padding-left:10px;
padding-right:5px;
margin-right:5px;
width: 20px;
height: 10px;
padding-left: 10px;
padding-right: 5px;
margin-right: 5px;
border-radius: 5px;
margin-bottom: 10px;
position: relative;
}

.vpd-bar-view .vpd-state span {
position: absolute;
top: -2px;
right: 20px;
width: auto;
display: inline-block;
background: #333333;
color: white;
padding: 2px 6px !important;
white-space: nowrap;
font-size: 11px;
text-align: center;
border-radius: 4px;
pointer-events: none;
opacity: 0;
}

.vpd-bar-view .vpd-state:hover span {
opacity: 1 !important;
z-index: 1;
}

.vpd-bar-view .vpd-state-legend span:first-child + span, .vpd-bar-view .vpd-state-legend span:first-child:hover + span {
position: absolute;
top: -2px;
left: 20px;
width: auto;
display: inline-block;
background: #333333;
color: white;
padding: 2px 6px;
white-space: nowrap;
font-size: 11px;
text-align: center;
border-radius: 4px;
pointer-events: none;
}

.vpd-bar-view .vpd-state-legend span:first-child:hover {
cursor: pointer;
}

.vpd-bar-view .vpd-state-legend span:first-child:hover + span {
opacity: 1 !important;
z-index: 1;
}

.vpd-bar-view .vpd-state-legend span:last-child {
margin-right:5px;
margin-right: 5px;
position: absolute;
opacity: 0;
transition: opacity 0.3s;
}


.clearfix::after {
content: "";
clear: both;
display: table;
}

.vpd-bar-view .grey-danger-zone {
background-color: #999999;
}

.vpd-bar-view .danger-zone {
background-color: #ce4234;
}

.vpd-bar-view .early-veg {
background-color: #22ab9c;
}

.vpd-bar-view .late-veg {
background-color: #9cc55b;
}

.vpd-bar-view .mid-late-flower {
background-color: #e7c12b;
}

.vpd-bar-view .under-transpiration {
background-color: #1a6c9c;
}

.vpd-bar-view .vpd-state.under-transpiration::before {
background: linear-gradient(-90deg, rgba(26,108,156,0.47) 0%, rgba(26, 108, 156, 0) 100%);
background: linear-gradient(-90deg, rgba(26, 108, 156, 0.47) 0%, rgba(26, 108, 156, 0) 100%);
content: "";
position: absolute;
top: 0;
Expand All @@ -85,6 +164,7 @@
bottom: 0;
border-radius: 5px;
}

.vpd-bar-view .vpd-state.grey-danger-zone::before {
background: linear-gradient(-90deg, rgba(153, 153, 153, 0.47) 0%, rgba(26, 108, 156, 0) 100%);
content: "";
Expand All @@ -97,7 +177,7 @@
}

.vpd-bar-view .vpd-state.danger-zone::before {
background: linear-gradient(-90deg, rgba(206,66,52,0.47) 0%, rgba(206, 66, 52, 0) 100%);
background: linear-gradient(-90deg, rgba(206, 66, 52, 0.47) 0%, rgba(206, 66, 52, 0) 100%);
content: "";
position: absolute;
top: 0;
Expand Down
84 changes: 42 additions & 42 deletions dist/bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,17 @@ export const bar = {
<style>
@import '/hacsfiles/ha-vpd-chart/bar.css?v=${window.vpdChartVersion}'
</style>
<div class="vpd-card-container card-content"></div>
<div class="card-content"></div>
<div class="highlight mousePointer" style="opacity:0">
<div class="custom-tooltip"></div>
</div> <!-- Tooltip -->
<!-- add Legend for VPD Phases -->
<div class="legend">
<span class="vpd-state-legend">
<span class="grey-danger-zone"></span>
<span class="vpd-title">Danger Zone</span>
</span>
<span class="vpd-state-legend">
<span class="under-transpiration"></span>
<span class="vpd-title">Under Transpiration</span>
</span>
<span class="vpd-state-legend">
<span class="early-veg"></span>
<span class="vpd-title">Early Veg</span>
</span>
<span class="vpd-state-legend">
<span class="late-veg"></span>
<span class="vpd-title">Late Veg</span>
</span>
<span class="vpd-state-legend">
<span class="mid-late-flower"></span>
<span class="vpd-title">Mid Late Flower</span>
</span>
<span class="vpd-state-legend">
<span class="danger-zone"></span>
<span class="vpd-title">Danger Zone</span>
</span>
<div class="clearfix"></div>
</div>
</ha-card>
`;
this.content = this.querySelector("div.vpd-card-container");
this.content = this.querySelector("div.card-content");

this.config.sensors.forEach((sensor) => {
let humidity = this._hass.states[sensor.humidity].state;
Expand All @@ -52,9 +29,9 @@ export const bar = {
if (sensor.vpd !== undefined) {
vpd = this._hass.states[sensor.vpd].state;
} else {
vpd = this.calculateVPD(parseFloat(leafTemperature), parseFloat(temperature), parseFloat(humidity)).toFixed(2);
vpd = this.calculateVPD(this.toFixedNumber(leafTemperature), this.toFixedNumber(temperature), this.toFixedNumber(humidity)).toFixed(2);
}
// check if already exist

let card = this.content.querySelector(`ha-card[data-sensor="${sensor.name}"]`);
if (!card) {
card = document.createElement('ha-card');
Expand All @@ -68,8 +45,8 @@ export const bar = {
}
html += `<span class="vpd-value">${vpd} ${this.kpa_text || ''}</span>`;
html += `<span class="vpd-rh">${humidity}%</span>`;
html += `<span class="vpd-temp">${temperature}°C</span>`;
html += `<span class="vpd-state ${this.getPhaseClass(vpd)} tooltip"></span>`;
html += `<span class="vpd-temp">${temperature} ${this.unit_temperature}</span>`;
html += `<span style="background: ${this.getColorForVpd(vpd)}" class="vpd-state ${this.getPhaseClass(vpd)}"><span>${this.getPhaseClass(vpd)}</span></span>`;
html += `<span class="vpd-history" style="float:right;"><canvas></canvas></span>`;
html += `</div>`;
card.innerHTML = html;
Expand All @@ -78,7 +55,29 @@ export const bar = {
}

this.updateBars();
this.updateVPDLegend();

},
updateVPDLegend() {
const legend = this.querySelector('.legend');
this.vpd_phases.forEach((phase) => {
const div = this.querySelector(`.vpd-${phase.className}`) || document.createElement('div');

div.className = `vpd-state-legend vpd-${phase.className}`;

if (!div.isConnected) {
div.innerHTML = `
<span class="${phase.className}" style="background: ${phase.color};"></span>
<span class="vpd-title">${phase.className}</span>
`;
legend.appendChild(div);
}
});
const clearfix = this.querySelector('.clearfix') || document.createElement('div');
clearfix.className = 'clearfix';
if (!clearfix.isConnected) {
legend.appendChild(clearfix);
}
},
updateBars() {
this.config.sensors.forEach((sensor, index) => {
Expand All @@ -92,18 +91,19 @@ export const bar = {
if (sensor.vpd !== undefined) {
vpd = this._hass.states[sensor.vpd].state;
} else {
vpd = this.calculateVPD(parseFloat(leafTemperature), parseFloat(temperature), parseFloat(humidity)).toFixed(2);
vpd = this.calculateVPD(this.toFixedNumber(leafTemperature), this.toFixedNumber(temperature), this.toFixedNumber(humidity)).toFixed(2);
}
let card = this.content.querySelector(`ha-card[data-sensor="${sensor.name}"]`);
// get the bar from card
let bar = card.querySelector('.bar');
bar.querySelector('.vpd-title').innerText = sensor.name;
bar.querySelector('.vpd-value').innerText = `${vpd} ${this.kpa_text}`;
bar.querySelector('.vpd-rh').innerText = `${humidity}%`;
bar.querySelector('.vpd-temp').innerText = `${temperature}°C`;

bar.querySelector('.vpd-temp').innerText = `${temperature}${this.unit_temperature}`;
bar.querySelector('.vpd-state span').innerText = this.getPhaseClass(vpd);
bar.querySelector('.vpd-state').style.background = this.getColorForVpd(vpd);
if (this.enable_ghostmap) {
if(!this.updateRunning) {
if (!this.updateRunning) {

this.renderMiniHistory(sensor).then((data) => {
this.updateRunning = true;
Expand All @@ -118,8 +118,8 @@ export const bar = {
const width = canvas.width - 2 * padding;
const height = canvas.height - 2 * padding;
const sensorData = data['sensor-' + index];
const maxY = Math.max(...sensorData.map(data => parseFloat(data.vpd)));
const minY = Math.min(...sensorData.map(data => parseFloat(data.vpd)));
const maxY = Math.max(...sensorData.map(data => this.toFixedNumber(data.vpd)));
const minY = Math.min(...sensorData.map(data => this.toFixedNumber(data.vpd)));
const scaleX = width / (sensorData.length - 1);
const scaleY = height / (maxY - minY);

Expand All @@ -128,8 +128,8 @@ export const bar = {

sensorData.forEach((data, index) => {
const x = index * scaleX + padding;
const y = padding + height - (parseFloat(data.vpd) - minY) * scaleY;
const color = this.getColorForVpd(parseFloat(data.vpd));
const y = padding + height - (this.toFixedNumber(data.vpd) - minY) * scaleY;
const color = this.getColorForVpd(this.toFixedNumber(data.vpd));

ctx.beginPath();
ctx.moveTo(x, y);
Expand Down Expand Up @@ -167,19 +167,19 @@ export const bar = {
}
return '';
},
async renderMiniHistory(sensor) {
async renderMiniHistory() {

const data = [];
for (const [index, sensor] of this.config.sensors.entries()) {
data['sensor-'+index] = [];
data['sensor-' + index] = [];
const temperaturesPromise = this.getEntityHistory(sensor.temperature);
const humiditiesPromise = this.getEntityHistory(sensor.humidity);

const [temperatures, humidities] = await Promise.all([temperaturesPromise, humiditiesPromise]);
temperatures.forEach((temperature, tempIndex) => {
data['sensor-'+index].push({
data['sensor-' + index].push({
time: temperature.last_changed,
vpd: this.calculateVPD(parseFloat(temperature.state) - (this.config.leaf_temperature_offset || 2), parseFloat(temperature.state), parseFloat(humidities[tempIndex].state)).toFixed(2),
vpd: this.calculateVPD(this.toFixedNumber(temperature.state) - (this.config.leaf_temperature_offset || 2), this.toFixedNumber(temperature.state), this.toFixedNumber(humidities[tempIndex].state)).toFixed(2),
});
});
}
Expand Down
Loading

0 comments on commit 8e5cef1

Please sign in to comment.