SOLUTION: Tooltip with data_generator + standard sensors
I found a “neat” solution that I would like to share.
The issue that a shared tooltip isn’t working seems to be a bug in Apex Charts itself, rather than the implementation in HA.
There was already an issue raised (Shared tooltip not working with data_generator · Issue #593 · RomRider/apexcharts-card · GitHub) and also the solution is mentioned there.
The code works fine and now the result looks as follows also including the values from the data_generator
function:
I added some further tweaks (code below):
- Time stamp was missing in the tooltip’s header
- Number format (I use the German number formatting with comma as decimal separator and dot as thousands separator)
- Show “n/a” for data points with no data - the initial code from the links above shows the last known value
This is the improved code:
type: custom:apexcharts-card
graph_span: 1d
span:
end: day
all_series_config:
fill_raw: last
extend_to: false
show:
legend_value: false
header:
show: false
apex_config:
stroke:
show: true
width: 1
dashArray:
- 2
- 0
dataLabels:
enabled: true
chart:
height: 560px
legend:
showForZeroSeries: true
tooltip:
enabled: true
shared: true
fixed: true
custom: |
EVAL:function a({ series, seriesIndex, dataPointIndex, w }) {
const hoverXaxis = w.globals.seriesX[seriesIndex][dataPointIndex];
const seriesX = w.globals.seriesX.map((seriesX) => {
return seriesX.findIndex(x => x >= hoverXaxis);
});
// Function to format numbers with comma as decimal separator and dot as thousands separator
function formatNumber(value) {
const [integerPart, decimalPart] = value.toFixed(1).split('.');
return integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, '.') + ',' + decimalPart;
}
let hoverList = "";
w.globals.seriesNames.forEach((seriesName, seriesEachIndex) => {
const data = series[seriesEachIndex];
const index = seriesX[seriesEachIndex];
let value;
if (index >= 0 && index < data.length && w.globals.seriesX[seriesEachIndex][index] >= hoverXaxis) {
value = data[index];
} else {
value = 'n/a';
}
hoverList += `
<div class="apexcharts-tooltip-series-group apexcharts-active" style="order: 1; display: flex;">
<span class="apexcharts-tooltip-marker" style="background-color: ${
w.globals.markers.colors[seriesEachIndex]
};"></span>
<div class="apexcharts-tooltip-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">
<div class="apexcharts-tooltip-y-group">
<span class="apexcharts-tooltip-text-y-label">${
seriesName
}: </span>
<span class="apexcharts-tooltip-text-y-value">${value === 'n/a' ? value : formatNumber(value)}</span>
</div>
</div>
</div>`;
});
const date = new Date(hoverXaxis);
const formattedDate = date.toLocaleDateString('en-GB', {
day: '2-digit',
month: 'short',
year: 'numeric'
});
const formattedTime = date.toLocaleTimeString('en-GB', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
return `<div class="apexcharts-tooltip-title" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">${
formattedDate + ", " + formattedTime
}</div>${hoverList}`;
}
series:
- entity: sensor.solcast_pv_forecast_prognose_heute
name: PV-Forecast
data_generator: |
return entity.attributes.detailedForecast.map((entry) => {
return [new Date(entry.period_start), (entry.pv_estimate * 1000)];
});
color: lightgrey
group_by:
func: avg
duration: 1min
- entity: sensor.inverter_pv_leistung
type: area
name: PV-Eingangsleistung
color: '#37872D'
opacity: 0.2
group_by:
func: avg
duration: 1min
- entity: sensor.inverter_eingangsleistung_verlustkorrigiert
color: '#73BF69'
name: PV-Eingangsleistung (verlustkorr.)
group_by:
func: avg
duration: 1min
- entity: sensor.hausverbrauchsleistung
type: area
color: '#B877D9'
opacity: 0.2
name: Gesamtverbrauch
group_by:
func: avg
duration: 1min
- entity: sensor.power_meter_netzbezug
type: area
color: '#F2495C'
opacity: 0.2
name: Netzbezug
group_by:
func: avg
duration: 1min
- entity: sensor.battery_lade_entladeleistung_verlustkorrigiert
type: area
color: '#5794F2'
opacity: 0.2
name: Akku Ladung/Entladung
group_by:
func: avg
duration: 1min
- entity: sensor.power_meter_netzeinspeisung
type: area
invert: true
color: '#FF9830'
opacity: 0.2
name: Netzeinspeisung
group_by:
func: avg
duration: 1min
.
QUESTION (further improvement):
Does anyone know, which object the unit of measurement is stored in within an Apex chart card?
I would like to read the respective data series’ unit of measurement and plot it along with the values within the tooltip.
Cheers,
Mat
EDIT:
Updated Code: ApexCharts card - A highly customizable graph card - #3699 by madmat17