Skip to content

Cookbook A2 Adding a Pie Chart

MyHomeMyData edited this page May 7, 2026 · 4 revisions

Cookbook A2 — Adding a Pie Chart

What you will build

A combined chart: the stacked area chart from A1 in the lower half, and a pie chart in the upper half showing the total energy share per category for the whole week.

flexcharts_wiki_a2_1

Just as in A1, the chart state remains the master for the chart definition. You will:

  1. Update the chart state with a new JSON that adds the pie chart structure and adjusts the layout
  2. Update the script — it now also fills in the weekly totals for the pie slices

The browser URL and the three energy data states stay completely unchanged.

Prerequisites

Completed Cookbook A1, Part B — the following must be in place:

  • State 0_userdata.0.flexcharts.energy.chart (chart output)
  • States 0_userdata.0.energy.consumption.household, .wallbox, .heatpump (data)
  • The update script from A1 Part B running in the JavaScript adapter

Step 1 — Update the chart state

Open 0_userdata.0.flexcharts.energy.chart in the Objects editor, replace its value with the JSON below, and save (ack unchecked).

This is the same chart definition as before, with three additions:

  • "grid": { "top": "55%" } — pushes the area chart into the lower half of the page
  • "tooltip": { "trigger": "item" } — works for both area chart and pie
  • A new pie series with placeholder values ("value": 0) — the script will fill these in
{
  "title":   { "text": "Weekly Energy Consumption", "left": "center" },
  "tooltip": { "trigger": "item" },
  "legend":  { "data": ["Household", "Wallbox", "Heat pump"], "top": "8%" },
  "toolbox": { "feature": { "saveAsImage": {} } },
  "grid":    { "top": "55%" },
  "xAxis": [{ "type": "category", "boundaryGap": false,
              "data": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] }],
  "yAxis": [{ "type": "value", "name": "kWh" }],
  "series": [
    { "name": "Household", "type": "line", "stack": "Total", "color": "#5b8dd9",
      "areaStyle": {}, "emphasis": { "focus": "series" }, "data": [] },
    { "name": "Wallbox",   "type": "line", "stack": "Total", "color": "#00a3a3",
      "areaStyle": {}, "emphasis": { "focus": "series" }, "data": [] },
    { "name": "Heat pump", "type": "line", "stack": "Total", "color": "#3a5fa0",
      "areaStyle": {}, "emphasis": { "focus": "series" }, "data": [] },
    { "type": "pie", "center": ["50%", "28%"], "radius": "30%",
      "label": { "formatter": "{b}: {c} kWh ({d}%)" },
      "data": [
        { "name": "Household", "value": 0, "itemStyle": { "color": "#5b8dd9" } },
        { "name": "Wallbox",   "value": 0, "itemStyle": { "color": "#00a3a3" } },
        { "name": "Heat pump", "value": 0, "itemStyle": { "color": "#3a5fa0" } }
      ]
    }
  ]
}

Note: The line series now have "data": [] — the script fills them in, so the initial placeholder is empty. The pie slices start with "value": 0 for the same reason. All visual settings (colors, layout, labels) are defined here in the state, not in the script.

Step 2 — Update the script

Replace the script from A1 Part B with the version below. The script still only updates data — but it now handles two chart types: line series (daily arrays) and pie slices (weekly totals).

const stateHousehold = '0_userdata.0.energy.consumption.household';
const stateWallbox   = '0_userdata.0.energy.consumption.wallbox';
const stateHeatpump  = '0_userdata.0.energy.consumption.heatpump';
const chartState     = '0_userdata.0.flexcharts.energy.chart';

createState(chartState, '', { name: 'Energy chart', type: 'string', role: 'json', read: true, write: true }, () => {
    buildAndSaveChart();
});

for (const id of [stateHousehold, stateWallbox, stateHeatpump]) {
    on({ id: id, ack: false }, () => { buildAndSaveChart(); });
}

function buildAndSaveChart() {
    const household = JSON.parse(getState(stateHousehold).val || '[]');
    const wallbox   = JSON.parse(getState(stateWallbox).val   || '[]');
    const heatpump  = JSON.parse(getState(stateHeatpump).val  || '[]');

    const sum    = arr => arr.reduce((a, b) => a + b, 0);
    const dataMap = { 'Household': household, 'Wallbox': wallbox, 'Heat pump': heatpump };

    // Read the chart definition from the state — the script only updates the data values.
    const option = JSON.parse(getState(chartState).val || '{}');

    for (const s of option.series || []) {
        if (s.type === 'line' && s.name in dataMap) {
            // Fill in the daily values for each area chart series.
            s.data = dataMap[s.name];
        } else if (s.type === 'pie') {
            // Fill in the weekly total for each pie slice.
            for (const item of s.data || []) {
                if (item.name in dataMap) item.value = sum(dataMap[item.name]);
            }
        }
    }

    setState(chartState, JSON.stringify(option), true);
}

Step 3 — Open in the browser

The URL is unchanged from A1:

http://localhost:8082/flexcharts/echarts.html?source=state&id=0_userdata.0.flexcharts.energy.chart&sse

The combined chart should appear immediately. Try changing a value in one of the energy states (ack unchecked) — both the area chart and the pie update together.

flexcharts_wiki_a2_2

How the script handles two chart types

The script loops over all series in the chart definition and acts differently depending on the series type:

for (const s of option.series || []) {
    if (s.type === 'line' && s.name in dataMap) {
        s.data = dataMap[s.name];           // daily array  → line series
    } else if (s.type === 'pie') {
        for (const item of s.data || []) {
            if (item.name in dataMap)
                item.value = sum(dataMap[item.name]);  // weekly total → pie slice
        }
    }
}

All other properties — colors, label formatter, center position, radius, grid layout — stay exactly as you defined them in the chart state. The script never touches them.

Note: The legend controls both the area series and the corresponding pie slice — clicking "Wallbox" in the legend hides the Wallbox area and its pie slice at the same time, because both share the same name.


What's next

  • Cookbook A3 — Make the pie react to hover events on the area chart using javascript-stringify