################################################################################################################### # There are multiple charts in this file, please copy each section into a different chart (starts with a comment) #################################################################################################################### --- ############################################### # Battery prediction chart ############################################### type: custom:apexcharts-card header: show: true title: Home Battery Prediction show_states: true colorize_states: true graph_span: 60h span: start: minute offset: '-12h' now: show: true yaxis: - min: 0 max: 9.54 series: - entity: predbat.soc_kw_h0 stroke_width: 1 curve: stepline name: actual extend_to: now show: in_header: raw - entity: predbat.soc_kw stroke_width: 1 curve: smooth name: base data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.soc_kw_best stroke_width: 3 curve: smooth name: best data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.soc_kw_best10 stroke_width: 1 curve: smooth name: best10 data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.best_charge_limit_kw stroke_width: 4 curve: stepline name: charge_limit_best type: area opacity: 0.2 data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.charge_limit_kw stroke_width: 1 curve: stepline name: charge_limit_base data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.best_discharge_limit_kw stroke_width: 2 curve: stepline name: discharge_best data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.record stroke_width: 3 curve: stepline name: record type: area opacity: 0.5 color: black data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.soc_kw_base10 stroke_width: 1 curve: smooth name: base10 data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw ############################################### # This is a cost chart ############################################### type: custom:apexcharts-card header: show: true title: Home cost prediction show_states: true colorize_states: true graph_span: 48h span: start: day offset: +0h now: show: true series: - entity: predbat.metric stroke_width: 1 curve: smooth name: base data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.best_metric stroke_width: 2 curve: smooth name: best data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.best10_metric stroke_width: 1 curve: smooth name: best10 data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.cost_today stroke_width: 1 curve: smooth name: actual extend_to: now data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.cost_today_import stroke_width: 1 curve: smooth name: actual_import extend_to: now data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.cost_today_export stroke_width: 1 curve: smooth name: actual_export extend_to: now data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), -value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.base10_metric stroke_width: 1 curve: smooth name: base10 data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw ############################################### # Energy rate chart # NOTE: Tune the value*5 in the grid_power_best part to make the power peak line up with the energy rates # so you can see charging/discharging aligned with slots ############################################### type: custom:apexcharts-card header: show: true title: Energy rates show_states: true colorize_states: true graph_span: 72h span: start: day offset: +0h now: show: true series: - entity: predbat.grid_power_best name: power stroke_width: 1 type: area opacity: 0.2 data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value*5]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.rates attribute: threshold name: Low threshold curve: stepline stroke_width: 2 - entity: predbat.rates_export attribute: threshold name: High threshold curve: stepline stroke_width: 2 - entity: predbat.rates stroke_width: 2 curve: stepline name: import data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.rates_export stroke_width: 1 type: area opacity: 0.2 curve: stepline name: export data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw ############################################### # Data prediction chart (import/export/pv/load) ############################################### type: custom:apexcharts-card header: show: true title: Data prediction show_states: true colorize_states: true graph_span: 48h span: start: minute offset: '-1h' now: show: true yaxis: - min: 0 series: - entity: predbat.load_energy_h0 stroke_width: 1 curve: smooth name: load actual extend_to: now - entity: predbat.import_energy_h0 stroke_width: 1 curve: smooth name: import actual extend_to: now - entity: predbat.export_energy_h0 stroke_width: 1 curve: smooth name: export actual extend_to: now - entity: predbat.pv_energy_h0 stroke_width: 1 curve: smooth name: PV actual extend_to: now - entity: predbat.best_load_energy stroke_width: 1 curve: smooth name: load show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.best_pv_energy stroke_width: 1 curve: smooth name: pv show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.import_energy stroke_width: 1 curve: smooth name: import show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.export_energy stroke_width: 1 curve: smooth name: export show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.best_import_energy stroke_width: 1 curve: smooth name: best import show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.best_export_energy stroke_width: 1 curve: smooth name: best export show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) ############################################################################################## # Example car battery prediction chart # Change sensor.tsunami_battery to your own car battery % sensor ############################################################################################## type: custom:apexcharts-card header: show: true title: Car battery prediction show_states: true colorize_states: true graph_span: 58h span: start: minute offset: '-12h' now: show: true yaxis: - min: 0 max: 100 series: - entity: sensor.tsunami_battery stroke_width: 1 curve: smooth name: history extend_to: now - entity: predbat.car_soc stroke_width: 1 curve: smooth name: base show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.car_soc_best stroke_width: 1 curve: smooth name: Best show: in_header: raw data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) ############################################### ## Power chart ############################################### type: custom:apexcharts-card header: show: true title: Power show_states: true colorize_states: true graph_span: 48h span: start: minute offset: '-0h' now: show: true series: - entity: predbat.battery_power_best stroke_width: 1 curve: smooth name: battery best unit: w data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value*1000.0]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.pv_power_best stroke_width: 1 curve: smooth name: pv best unit: w data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value*1000.0]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.grid_power_best stroke_width: 1 curve: smooth name: grid best unit: w data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value*1000.0]); } return res.sort((a, b) => { return a[0] - b[0] }) - entity: predbat.load_power_best stroke_width: 1 curve: smooth name: load best unit: w data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value*1000.0]); } return res.sort((a, b) => { return a[0] - b[0] }) ############################################### # Calibration chart ############################################### type: custom:apexcharts-card header: show: true title: Calibration show_states: true colorize_states: true graph_span: 48h span: start: minute offset: '-36h' now: show: true yaxis: - min: 0 series: - entity: predbat.soc_kw_h0 stroke_width: 1 curve: smooth name: actual extend_to: now show: in_header: raw - entity: predbat.soc_kw_best_h1 stroke_width: 1 curve: smooth name: h1 offset: '-1h' show: in_header: raw - entity: predbat.soc_kw_best_h8 stroke_width: 1 curve: smooth name: h8 offset: '-8h' show: in_header: raw - entity: predbat.soc_kw_best_h12 stroke_width: 1 curve: smooth name: h12 offset: '-12h' show: in_header: raw ############################################### # In day adjustment chart ############################################### type: custom:apexcharts-card header: show: true title: In day adjustment show_states: true colorize_states: true graph_span: 24h span: start: day offset: '-0h' now: show: true yaxis: - min: 0 series: - entity: predbat.load_energy_actual stroke_width: 1 curve: smooth name: actual data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.load_energy_predicted stroke_width: 1 curve: smooth name: predicted data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.load_energy_adjusted stroke_width: 1 curve: smooth name: adjusted data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw ############################################### # Carbon chart ############################################### type: custom:apexcharts-card header: show: true title: Home cost prediction show_states: true colorize_states: true graph_span: 48h span: start: day offset: +0h now: show: true series: - entity: predbat.carbon_today stroke_width: 1 curve: smooth name: co2 data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) extend_to: now show: in_header: raw - entity: predbat.carbon_best stroke_width: 2 curve: smooth name: co2 best data_generator: > let res = []; for (const [key, value] of Object.entries(entity.attributes.results)) { res.push([new Date(key).getTime(), value]); } return res.sort((a, b) => { return a[0] - b[0] }) show: in_header: raw - entity: predbat.carbon_now stroke_width: 4 curve: smooth name: Carbon Intensity history show: in_header: raw extend_to: now - entity: sensor.carbon_intensity_uk unit: g/kWh name: Carbon Intensity future show: legend_value: false data_generator: | return entity.attributes.forecast.map(obj => { return [new Date(obj.from).getTime(), obj.intensity]; }); color_threshold: - value: 25 color: darkgreen opacity: 1 - value: 95 color: green - value: 180 color: gold - value: 279 color: red - value: 330 color: darkred ############################################### # Daily cost saving chart ############################################### type: custom:apexcharts-card header: show: true title: Daily Cost Savings show_states: true colorize_states: true graph_span: 7days span: start: day offset: '-6day' now: show: true series: - entity: predbat.savings_yesterday_predbat stroke_width: 1 name: saving_predbat type: column group_by: func: last duration: 24hours - entity: predbat.savings_yesterday_pvbat stroke_width: 1 name: saving_pvbat type: column group_by: func: last duration: 1day - entity: predbat.cost_yesterday stroke_width: 1 type: column name: actual group_by: func: last duration: 1day ############################################### # Total cost saving chart ############################################### type: custom:apexcharts-card header: show: true title: Total Cost Saving show_states: true colorize_states: true graph_span: 30days span: start: day offset: '-29days' now: show: true series: - entity: predbat.savings_total_predbat stroke_width: 1 curve: smooth name: Predbat saving attribute: pounds unit: £ - entity: predbat.savings_total_pvbat stroke_width: 1 curve: smooth name: PV/Battery saving attribute: pounds unit: £ ############################################### # PV Forecast vs actual chart ############################################### type: custom:apexcharts-card header: title: Solar forecast show: true show_states: true colorize_states: true apex_config: chart: height: 300px tooltip: enabled: true shared: true followCursor: true graph_span: 24h span: start: day yaxis: - id: capacity show: true opposite: true decimals: 0 max: 100 min: 0 apex_config: tickAmount: 10 - id: kWh show: true min: 0 apex_config: tickAmount: 10 - id: header_only show: false series: - entity: sensor.givtcp_sa2243g277_pv_power name: Solar Power type: line stroke_width: 2 float_precision: 2 color: Orange yaxis_id: kWh unit: kW transform: return x/1000; extend_to: now show: legend_value: true in_header: false group_by: func: avg duration: 5m - entity: sensor.predbat_pv_today name: Forecast color: grey opacity: 0.3 stroke_width: 0 type: area extend_to: false yaxis_id: kWh show: legend_value: false in_header: false data_generator: | return entity.attributes.detailedForecast.map((entry) => { return [new Date(entry.period_start), entry.pv_estimate]; }); - entity: sensor.predbat_pv_today name: Forecast 10% color: grey opacity: 0.3 stroke_width: 0 type: area extend_to: false yaxis_id: kWh show: legend_value: false in_header: false data_generator: | return entity.attributes.detailedForecast.map((entry) => { return [new Date(entry.period_start), entry.pv_estimate10]; }); - entity: sensor.givtcp_sa2243g277_pv_energy_today_kwh yaxis_id: header_only name: Today Actual stroke_width: 2 color: Orange show: legend_value: true in_header: true in_chart: false - entity: sensor.predbat_pv_today yaxis_id: header_only name: Today Forecast color: Grey show: legend_value: true in_header: true in_chart: false - entity: sensor.predbat_pv_today yaxis_id: header_only attribute: remaining name: Remaining color: Grey show: legend_value: true in_header: true in_chart: false