Max Solar Power Heatmap over Azimut and Elevation #408
Replies: 4 comments 18 replies
-
Really cool! |
Beta Was this translation helpful? Give feedback.
-
Is there a way to render a cross or dot for the current Elevation/Azimuth on top of the heatmap? |
Beta Was this translation helpful? Give feedback.
-
Totally. I’m traveling so I can only past a bit ugly
- entity: sensor.sun_solar_elevation x: >- $fn ({ hass }) =>
[1,1].map(x=>parseFloat(hass.states['sensor.sun_solar_azimuth'].state))
'y': >- $fn ({ hass }) =>
[1,1].map(x=>parseFloat(hass.states['sensor.sun_solar_elevation'].state))
z: >- $fn ({ hass }) =>
[1,1].map(x=>parseFloat(hass.states['sensor.solar_power'].state)) type:
scatter mode: markers marker: size: - 15 - 7 color: - black - yellow
symbol: - circle - star
Ladislav Feldsam ***@***.***> schrieb am Di. 21. Mai 2024 um
09:50:
… Is there a way to render a cross or dot for the current Elevation/Azimuth
on top of the heatmap?
—
Reply to this email directly, view it on GitHub
<#408 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAS47MV7W5TWVTUMN3RVSELZDL4FZAVCNFSM6AAAAABGGBGIYGVHI2DSMVQWIX3LMV43SRDJONRXK43TNFXW4Q3PNVWWK3TUHM4TKMBVGEZDA>
.
You are receiving this because you authored the thread.Message ID:
<dbuezas/lovelace-plotly-graph-card/repo-discussions/408/comments/9505120@
github.com>
|
Beta Was this translation helpful? Give feedback.
-
i have improved your code a bit. type: custom:plotly-graph
raw_plotly_config: true
hours_to_show: 1y
refresh_interval: 5m
title: Max Solar Power [W]
layout:
autosize: true
margin:
t: 0
l: 55
r: 45
b: 65
xaxis:
title: Azimuth [°]
yaxis:
title: Elevation [°]
entities:
- entity: sensor.sun_solar_azimuth
internal: true
period: 5minute
fn: |-
$fn ({ xs, ys, vars }) => {
vars.azimuth_raw_x_ = xs.map(x => x.getTime());
vars.azimuth_raw_y_ = ys;
}
- entity: sensor.sun_solar_azimuth
internal: true
statistic: mean
period: hour
fn: |-
$fn ({ xs, ys, vars }) => {
const xs_ = xs.map(x => x.getTime());
const i = xs_.findIndex(x => x > vars.azimuth_raw_x_[0]);
vars.azimuth_raw_x = xs_.slice(0, i);
vars.azimuth_raw_y = ys.slice(0, i);
}
- entity: sensor.sun_solar_elevation
internal: true
period: 5minute
fn: |-
$fn ({ xs, ys, vars }) => {
vars.elevation_raw_x_ = xs.map(x => x.getTime());
vars.elevation_raw_y_ = ys;
}
- entity: sensor.sun_solar_elevation
internal: true
statistic: mean
period: hour
fn: |-
$fn ({ xs, ys, vars }) => {
const xs_ = xs.map(x => x.getTime());
const i = xs_.findIndex(x => x > vars.elevation_raw_x_[0]);
vars.elevation_raw_x = xs_.slice(0, i);
vars.elevation_raw_y = ys.slice(0, i);
}
- entity: sensor.solar_power
internal: true
period: 5minute
fn: |-
$fn ({ xs, ys, vars }) => {
vars.power_raw_x_ = xs.map(x => x.getTime());
vars.power_raw_y_ = ys;
}
- entity: sensor.solar_power
internal: true
statistic: mean
period: hour
fn: |-
$fn ({ xs, ys, vars }) => {
const xs_ = xs.map(x => x.getTime());
const i = xs_.findIndex(x => x > vars.power_raw_x_[0]);
vars.power_raw_x = xs_.slice(0, i);
vars.power_raw_y = ys.slice(0, i);
}
- entity: ""
type: heatmap
hoverongaps: false
colorscale: Rainbow
fn: |-
$fn ({ xs, ys, vars }) => {
const x = Array.from({ length: 220 + 1 }, (e, i) => 70 + i);
const y = Array.from({ length: 55 + 1 }, (e, i) => 0 + i);
const z = Array(y.length).fill(null).map(() => Array(x.length).fill(NaN));
for (let i = 0; i < vars.power_raw_y.length; i++) {
const pw = vars.power_raw_y[i];
const ix = vars.power_raw_x[i];
const azi = vars.azimuth_raw_x.indexOf(ix);
const eli = vars.elevation_raw_x.indexOf(ix);
if (azi >= 0 && eli >= 0) {
const az = vars.azimuth_raw_y[azi];
const el = vars.elevation_raw_y[eli];
const pos_az_min = x.indexOf(Math.floor(az));
const pos_el_min = y.indexOf(Math.floor(el));
const pos_az_max = x.indexOf(Math.ceil(az));
const pos_el_max = y.indexOf(Math.ceil(el));
if (pos_az_min >= 0 && pos_el_min >= 0 && pos_az_max >= 0 && pos_el_max >= 0) {
for (let pos_az = pos_az_min; pos_az <= pos_az_max; pos_az++) {
for (let pos_el = pos_el_min; pos_el <= pos_el_max; pos_el++) {
if (isNaN(z[pos_el][pos_az])) {
z[pos_el][pos_az] = pw;
} else {
z[pos_el][pos_az] = Math.max(z[pos_el][pos_az], pw);
}
}
}
}
}
}
for (let i = 0; i < vars.power_raw_y_.length; i++) {
const pw = vars.power_raw_y_[i];
const ix = vars.power_raw_x_[i];
const azi = vars.azimuth_raw_x_.indexOf(ix);
const eli = vars.elevation_raw_x_.indexOf(ix);
if (azi >= 0 && eli >= 0) {
const az = vars.azimuth_raw_y_[azi];
const el = vars.elevation_raw_y_[eli];
const pos_az_min = x.indexOf(Math.floor(az));
const pos_el_min = y.indexOf(Math.floor(el));
const pos_az_max = x.indexOf(Math.ceil(az));
const pos_el_max = y.indexOf(Math.ceil(el));
if (pos_az_min >= 0 && pos_el_min >= 0 && pos_az_max >= 0 && pos_el_max >= 0) {
for (let pos_az = pos_az_min; pos_az <= pos_az_max; pos_az++) {
for (let pos_el = pos_el_min; pos_el <= pos_el_max; pos_el++) {
if (isNaN(z[pos_el][pos_az])) {
z[pos_el][pos_az] = pw;
} else {
z[pos_el][pos_az] = Math.max(z[pos_el][pos_az], pw);
}
}
}
}
}
}
vars.x = x;
vars.y = y;
vars.z = z;
};
x: $fn ({ vars }) => vars.x
"y": $fn ({ vars }) => vars.y
z: $fn ({ vars }) => vars.z |
Beta Was this translation helpful? Give feedback.
-
Please read entire post. Below others significantly improved the code - including but not limited to long term statistics.
Do you want to see, what your best solar power was over azimut and elevation? Then enjoy this:
Also inspired by 215
PS: Because the power is NaN at night, somehow the array azimuth/elevation compared to power had not the same length, therefore I passed on the xs'es to sort the power values in manually.
Beta Was this translation helpful? Give feedback.
All reactions