Wolf CHA heat pump – hydraulic schematic widget (ism7mqtt)

This widget shows a live hydraulic schematic of a Wolf CHA air-to-water heat pump: outdoor unit, indoor module, domestic hot water heat exchanger, mixer circuit and the most important sensor values.

The schematic is a responsive SVG that scales with the card width. Labels and states update live:

  • The compressor and fan are highlighted when running, and the fan animates.
  • The flow direction is animated when there is circulation (flow rate > 0).
  • The 3-way diverter valve (3WUV) switches between heating and DHW. The inactive path is dimmed.
  • The heating circuit pump (ZHP), mixer circuit pump (MKP) and electric heater (E-Heizung) change color when active.

The abbreviations (KF, SF, SAF, DFL, DHK, ZHP, MKP, MM, VF …) follow Wolf’s own hydraulic scheme, so they match the documentation and the display on the unit.

Requirements

  • openHAB 5 Main UI
  • ism7mqtt, which reads the data from the Wolf ISM7 interface and publishes it via MQTT
  • MQTT binding with the corresponding items

The status checks expect the German values delivered by ism7mqtt (e.g. “Ladung”, “Ein”, “Betrieb”, “Warmwasser”). If your installation reports different values, you may need to adjust the functions in the oh-context at the top of the widget.

Parameters

The Wolf datapoint number is noted in each parameter label, so you can easily find the matching value in ism7mqtt:

Parameter Description Wolf datapoint
outsideTemp Outside temperature 270005
flowTemp Flow temperature heat pump (VL) 340011
returnTemp Return temperature (RL) 270009
boilerTemp Boiler temperature (KF) 270044
flowRate Flow rate (DFL) 270028
pressure System pressure (DHK) 270030
dhwTemp DHW temperature (SF) 270007
dhwStatus DHW status 350001
collectorTemp Collector temperature (SAF) 270029
mixerFlowTemp Mixer circuit flow temperature (VF) 40028
mixerStatus Mixer circuit status (optional) 360005
valve3wuv 3-way diverter valve HZ/WW (optional) 270013
heatingPump Heating circuit pump ZHP (optional) 270012
mixerPump Mixer circuit pump MKP (optional) 40070
eHeater Electric heater status (optional) 270052
compressorFreq Compressor frequency 270048
fanSpeed Fan speed 270047
power Power consumption 270049
compressorStatus Compressor status 270051

Optional parameters can be left empty. For example, without valve3wuv the DHW mode is derived from dhwStatus, and without heatingPump the pump state is derived from the flow rate.

Credits

The widget was developed with the help of Claude (Anthropic’s AI assistant). Claude helped me build the SVG schematic, the logic in the oh-context and the layout fine-tuning. Feedback and improvements are welcome!

Changelog

  • Version 1.1.0 – Outdoor unit redesigned (heat exchanger, animated compressor and fan), new optional parameter “Compressor Status” (270051) to display the maximum thermostat setting.
  • Version 1.0.0 – initial release

Resources

version: 1
widgets:
  Widget_Wolf_CHA:
    tags:
      - Version 1.1.0
      - Heizung
      - Wolf
    props:
      parameters:
        - default: Wolf CHA
          label: Titel
          name: title
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Temperatur_Aussen
          label: Außentemperatur (270005)
          name: outsideTemp
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Vorlauftemperatur
          label: Vorlauftemperatur WP (VL) (340011) ToDo nicht klar Wert abgeriffen wird
          name: flowTemp
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Rucklauftemperatur
          label: Rücklauftemperatur (RL) (270009)
          name: returnTemp
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Kesseltemperatur_2
          label: Kesseltemperatur (KF) (270044)
          name: boilerTemp
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Heizkreisdurchfluss
          label: Durchfluss (DFL) (270028)
          name: flowRate
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Anlagendruck
          label: Anlagendruck (DHK) (270030)
          name: pressure
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Warmwassertemperatur
          label: Warmwassertemperatur (SF) (270007)
          name: dhwTemp
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Warmwasser_Status
          description: Warmwasser gilt als aktiv, wenn der Status 'Ladung' enthält (aber nicht 'keine Ladung'). Das Umschaltventil-Item hat Vorrang.
          label: Warmwasser-Status (350001)
          name: dhwStatus
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Temperatur_Sammler
          label: Sammlertemperatur (SAF) (270029)
          name: collectorTemp
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Verdichterfrequenz
          label: Verdichterfrequenz (270048)
          name: compressorFreq
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Drehzahl_Ventilator
          label: Drehzahl Ventilator (270047)
          name: fanSpeed
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Leistungsaufnahme_WP__EHZ
          label: Leistungsaufnahme (270049)
          name: power
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Vorlauftemperatur_MM
          label: Vorlauf Mischerkreis (VF) (40028)
          name: mixerFlowTemp
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Mischerkreis_Status
          description: Optional
          label: Mischerkreis-Status  (360005)
          name: mixerStatus
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_3WegeUmschaltventil_HZWW
          description: "Optional: Wolf-Datenpunkt '3-Wege-Umschaltventil HZ/WW' (Heizen/Warmwasser). Hat Vorrang vor dem Warmwasser-Status."
          label: 3-Wege-Umschaltventil HZ/WW  (270013)
          name: valve3wuv
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_ZubringerHeizkreispumpe
          description: "Optional: Wolf-Datenpunkt 'Zubringer-/Heizkreispumpe' (Ein/Aus). Ohne Item wird der Durchfluss ausgewertet."
          label: Heizkreispumpe (ZHP) (270012)
          name: heatingPump
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Mischerkreispumpe
          description: "Optional: Wolf-Datenpunkt 'Mischerkreispumpe' (Ein/Aus)"
          label: Mischerkreispumpe (MKP) (40070)
          name: mixerPump
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Status_E_Heizung
          description: "Optional: Wolf-Datenpunkt 'E-Heizung' (Ein/Aus)"
          label: Status E-Heizung (270052)
          name: eHeater
          required: false
          type: TEXT
        - context: item
          default: Wolf_Heatpump_Verdichter_Status
          description: "Optional: Wolf-Datenpunkt 'Verdichterstatus'. MaxTh wird rot markiert, wenn der Status 'MaxTh' enthält (z. B. 'TPW/MaxTh' oder 'MaxTH')."
          label: Verdichterstatus (270051)
          name: compressorStatus
          required: false
          type: TEXT
    component: oh-context
    config:
      constants:
        red: "#d62839"
        blue: "#4a90d9"
        unit: "#d4d4d8"
        unitStroke: "#a1a1aa"
        dark: "#52525b"
        part: "#f4f4f5"
        on: "#22c55e"
      functions:
        v: "=(item) => !item ? '–' : ((@@item === 'NULL' || @@item === 'UNDEF') ? '–' : @item)"
        flowing: "=() => !!props.flowRate && #props.flowRate > 0"
        compressorOn: "=() => !!props.compressorFreq && #props.compressorFreq > 0"
        fanOn: "=() => !!props.fanSpeed && #props.fanSpeed > 0"
        ww: =() => (!!props.valve3wuv && (('' + @@props.valve3wuv).includes('Warm') || ('' + @@props.valve3wuv) === 'WW')) || (!props.valve3wuv && !!props.dhwStatus && ('' + @@props.dhwStatus).includes('Ladung') && !('' + @@props.dhwStatus).includes('keine'))
        zhpOn: "=() => (!!props.heatingPump && ['Ein', 'ON', 'An'].indexOf('' + @@props.heatingPump) >= 0) || (!props.heatingPump && !!props.flowRate && #props.flowRate > 0)"
        mkpOn: =() => !!props.mixerPump && ['Ein', 'ON', 'An'].indexOf('' + @@props.mixerPump) >= 0
        ehzOn: =() => !!props.eHeater && ['Betrieb'].indexOf('' + @@props.eHeater) >= 0
        maxThOn: =() => !!props.compressorStatus && ('' + @@props.compressorStatus).toLowerCase().includes('maxth')
    slots:
      default:
        - component: f7-card
          config:
            style:
              border-radius: var(--f7-card-expandable-border-radius)
              box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
              margin-left: 5px
              margin-right: 5px
              padding: 8px
          slots:
            default:
              - component: Label
                config:
                  text: =props.title
                  style:
                    font-size: 17px
                    font-weight: bold
                    padding: 4px 8px
              - component: div
                config:
                  style:
                    margin: 0 auto
                    max-width: 600px
                    position: relative
                    width: 100%
                slots:
                  default:
                    - component: f7-row
                      config:
                        tag: svg
                        viewBox: 0 0 600 420
                        xmlns: http://www.w3.org/2000/svg
                        style:
                          display: block
                          height: auto
                          width: 100%
                        preserveAspectRatio: xMidYMid meet
                      slots:
                        default:
                          - component: f7-row
                            config:
                              tag: defs
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    tag: linearGradient
                                    id: wolfcha_saf
                                    x1: "0"
                                    y1: "0"
                                    x2: "0"
                                    y2: "1"
                                  slots:
                                    default:
                                      - component: f7-row
                                        config:
                                          tag: stop
                                          offset: "0"
                                          stop-color: "#d62839"
                                      - component: f7-row
                                        config:
                                          tag: stop
                                          offset: "1"
                                          stop-color: "#4a90d9"
                                - component: f7-row
                                  config:
                                    tag: linearGradient
                                    id: wolfcha_hx
                                    x1: "0"
                                    y1: "0"
                                    x2: "1"
                                    y2: "0"
                                  slots:
                                    default:
                                      - component: f7-row
                                        config:
                                          tag: stop
                                          offset: "0"
                                          stop-color: "#d62839"
                                      - component: f7-row
                                        config:
                                          tag: stop
                                          offset: "1"
                                          stop-color: "#4a90d9"
                          - component: f7-row
                            config:
                              tag: rect
                              x: 198
                              y: 66
                              width: 104
                              height: 92
                              rx: 6
                              fill: =const.unit
                              stroke: =const.unitStroke
                              style:
                                height: 92px
                                width: 104px
                          - component: f7-row
                            config:
                              tag: rect
                              x: 198
                              y: 178
                              width: 104
                              height: 128
                              rx: 6
                              fill: =const.unit
                              stroke: =const.unitStroke
                              style:
                                height: 128px
                                width: 104px
                          - component: f7-row
                            config:
                              tag: rect
                              x: 45
                              y: 248
                              width: 52
                              height: 82
                              rx: 8
                              fill: "#e4e4e7"
                              stroke: =const.unitStroke
                              style:
                                height: 82px
                                width: 52px
                          - component: f7-row
                            config:
                              comment: Kältekreis Leitungen
                              tag: path
                              d: M225 113 L232 105 H238 M225 131 L232 135 H238 M290 105 H296 V135 H290
                              fill: none
                              stroke: "#71717a"
                              stroke-width: 1.5
                              stroke-linejoin: round
                              transform: translate(0 -10)
                          - component: f7-row
                            config:
                              comment: Wärmetauscher oben (Verdampfer)
                              tag: rect
                              x: 238
                              y: 98
                              width: 52
                              height: 14
                              rx: 2
                              fill: url(#wolfcha_hx)
                              stroke: "#71717a"
                              stroke-width: 0.8
                              style:
                                height: 14px
                                width: 52px
                              transform: translate(0 -10)
                          - component: f7-row
                            config:
                              comment: Wärmetauscher unten (Verflüssiger)
                              tag: rect
                              x: 238
                              y: 128
                              width: 52
                              height: 14
                              rx: 2
                              fill: url(#wolfcha_hx)
                              stroke: "#71717a"
                              stroke-width: 0.8
                              style:
                                height: 14px
                                width: 52px
                              transform: translate(0 -10)
                          - component: f7-row
                            config:
                              comment: Verdichter
                              tag: circle
                              cx: 222
                              cy: 122
                              r: 10
                              fill: "=fn.compressorOn() ? '#86efac' : const.part"
                              stroke: =const.dark
                              stroke-width: 1.5
                              transform: translate(0 -10)
                          - component: f7-row
                            config:
                              comment: Verdichter-Symbol
                              tag: g
                              transform: translate(0 -10)
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    d: M214 116 L220 131 M230 116 L224 131
                                    fill: none
                                    stroke: =const.dark
                                    stroke-linecap: round
                                    stroke-width: 1.5
                                    tag: path
                                  slots:
                                    default:
                                      - component: f7-row
                                        config:
                                          attributeName: transform
                                          dur: 3s
                                          from: 0 222 122
                                          repeatCount: indefinite
                                          tag: animateTransform
                                          to: 360 222 122
                                          type: rotate
                                          visible: =fn.compressorOn()
                          - component: f7-row
                            config:
                              comment: Ventilator
                              tag: g
                              transform: translate(0 -10)
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    comment: Gehäuse
                                    cx: 264
                                    cy: 90
                                    fill: "=fn.fanOn() ? '#86efac' : const.part"
                                    r: 7
                                    stroke: =const.dark
                                    stroke-width: 1
                                    tag: circle
                                - component: f7-row
                                  config:
                                    comment: Rotor
                                    tag: g
                                  slots:
                                    default:
                                      - component: f7-row
                                        config:
                                          d: M264 90 C267 88 267 85.5 264 84.5 C262.5 85.5 262 88 264 90 Z
                                          fill: =const.dark
                                          tag: path
                                      - component: f7-row
                                        config:
                                          d: M264 90 C267 88 267 85.5 264 84.5 C262.5 85.5 262 88 264 90 Z
                                          fill: =const.dark
                                          tag: path
                                          transform: rotate(120 264 90)
                                      - component: f7-row
                                        config:
                                          d: M264 90 C267 88 267 85.5 264 84.5 C262.5 85.5 262 88 264 90 Z
                                          fill: =const.dark
                                          tag: path
                                          transform: rotate(240 264 90)
                                      - component: f7-row
                                        config:
                                          attributeName: transform
                                          dur: 1s
                                          from: 0 264 90
                                          repeatCount: indefinite
                                          tag: animateTransform
                                          to: 360 264 90
                                          type: rotate
                                          visible: =fn.fanOn()
                                - component: f7-row
                                  config:
                                    cx: 264
                                    cy: 90
                                    fill: =const.dark
                                    r: 1.2
                                    tag: circle
                          - component: f7-row
                            config:
                              comment: Wärmetauscher Rohrschlangen
                              tag: path
                              d: M243 110 L249 100 M251 110 L257 100 M259 110 L265 100 M267 110 L273 100 M275 110 L281 100 M283 110 L289 100 M243 140 L249 130 M251 140 L257 130 M259 140 L265 130 M267 140 L273 130 M275 140 L281 130 M283 140 L289 130
                              fill: none
                              stroke: rgba(255,255,255,0.7)
                              stroke-width: 1.2
                              stroke-linecap: round
                              transform: translate(0 -10)
                          - component: f7-row
                            config:
                              tag: path
                              d: M65 378 H530
                              fill: none
                              stroke: =const.red
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M65 400 H530
                              fill: none
                              stroke: =const.blue
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M276 400 V132
                              fill: none
                              stroke: =const.blue
                              stroke-width: 4
                          - component: f7-row
                            config:
                              tag: path
                              d: M246 132 V142 H222 V283
                              fill: none
                              stroke: =const.red
                              stroke-width: 4
                              stroke-linejoin: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M222 283 V378
                              fill: none
                              stroke: =const.red
                              stroke-width: 4
                              opacity: "=fn.ww() ? 0.3 : 1"
                          - component: f7-row
                            config:
                              tag: path
                              d: M222 283 H97
                              fill: none
                              stroke: =const.red
                              stroke-width: 4
                              opacity: "=fn.ww() ? 1 : 0.3"
                          - component: f7-row
                            config:
                              tag: path
                              d: M97 318 H276
                              fill: none
                              stroke: =const.blue
                              stroke-width: 4
                              opacity: "=fn.ww() ? 1 : 0.3"
                          - component: f7-row
                            config:
                              tag: path
                              d: M55 283 H88 M55 290 H88 M55 297 H88 M55 304 H88 M55 311 H88 M55 318 H88
                              fill: none
                              stroke: "#a1a1aa"
                              stroke-width: 0
                          - component: f7-row
                            config:
                              tag: path
                              d: M55 283 H88
                              stroke: "#d62839"
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M55 290 H88
                              stroke: "#b7446c"
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M55 297 H88
                              stroke: "#98609f"
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M55 304 H88
                              stroke: "#7a7cc2"
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M55 311 H88
                              stroke: "#5b8ad0"
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M55 318 H88
                              stroke: "#4a90d9"
                              stroke-width: 4
                              stroke-linecap: round
                          - component: f7-row
                            config:
                              tag: path
                              d: M216 340 H228 L222 352 Z
                              fill: =const.red
                              opacity: "=fn.ww() ? 0.3 : 1"
                          - component: f7-row
                            config:
                              tag: path
                              d: M270 352 H282 L276 340 Z
                              fill: =const.blue
                          - component: f7-row
                            config:
                              tag: path
                              d: M424 378 V93 H446
                              fill: none
                              stroke: =const.red
                              stroke-width: 4
                          - component: f7-row
                            config:
                              tag: path
                              d: M480 93 H505 V400
                              fill: none
                              stroke: =const.blue
                              stroke-width: 4
                          - component: f7-row
                            config:
                              tag: path
                              d: M424 243 H505
                              fill: none
                              stroke: =const.blue
                              stroke-width: 4
                          - component: f7-row
                            config:
                              tag: path
                              d: M418 306 H430 L424 294 Z
                              fill: =const.red
                          - component: f7-row
                            config:
                              tag: path
                              d: M499 294 H511 L505 306 Z
                              fill: =const.blue
                          - component: f7-row
                            config:
                              tag: circle
                              cx: 463
                              cy: 93
                              r: 17
                              fill: =const.unit
                              stroke: =const.unitStroke
                              stroke-width: 2
                          - component: f7-row
                            config:
                              tag: circle
                              cx: 463
                              cy: 93
                              r: 11
                              fill: =const.dark
                          - component: f7-row
                            config:
                              tag: path
                              d: M246 132 V142 H222 V283
                              fill: none
                              stroke: rgba(255,255,255,0.85)
                              stroke-width: 2
                              stroke-dasharray: 3 9
                              visible: =fn.flowing()
                              stroke-linejoin: round
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    tag: animate
                                    attributeName: stroke-dashoffset
                                    from: "12"
                                    to: "0"
                                    dur: 0.8s
                                    repeatCount: indefinite
                          - component: f7-row
                            config:
                              tag: path
                              d: M222 283 V378
                              fill: none
                              stroke: rgba(255,255,255,0.85)
                              stroke-width: 2
                              stroke-dasharray: 3 9
                              visible: =fn.flowing() && !fn.ww()
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    tag: animate
                                    attributeName: stroke-dashoffset
                                    from: "12"
                                    to: "0"
                                    dur: 0.8s
                                    repeatCount: indefinite
                          - component: f7-row
                            config:
                              tag: path
                              d: M222 283 H97
                              fill: none
                              stroke: rgba(255,255,255,0.85)
                              stroke-width: 2
                              stroke-dasharray: 3 9
                              visible: =fn.flowing() && fn.ww()
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    tag: animate
                                    attributeName: stroke-dashoffset
                                    from: "12"
                                    to: "0"
                                    dur: 0.8s
                                    repeatCount: indefinite
                          - component: f7-row
                            config:
                              tag: path
                              d: M97 318 H276
                              fill: none
                              stroke: rgba(255,255,255,0.85)
                              stroke-width: 2
                              stroke-dasharray: 3 9
                              visible: =fn.flowing() && fn.ww()
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    tag: animate
                                    attributeName: stroke-dashoffset
                                    from: "12"
                                    to: "0"
                                    dur: 0.8s
                                    repeatCount: indefinite
                          - component: f7-row
                            config:
                              tag: path
                              d: M276 400 V132
                              fill: none
                              stroke: rgba(255,255,255,0.85)
                              stroke-width: 2
                              stroke-dasharray: 3 9
                              visible: =fn.flowing()
                            slots:
                              default:
                                - component: f7-row
                                  config:
                                    tag: animate
                                    attributeName: stroke-dashoffset
                                    from: "12"
                                    to: "0"
                                    dur: 0.8s
                                    repeatCount: indefinite
                          - component: f7-row
                            config:
                              comment: Circle DHK
                              tag: circle
                              cx: 222
                              cy: 188
                              r: 8
                              fill: "#e4e4e7"
                              stroke: "#71717a"
                              stroke-width: 1.5
                          - component: text
                            config:
                              tag: text
                              x: 222
                              y: 188
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: P
                          - component: f7-row
                            config:
                              tag: rect
                              x: 215
                              y: 202
                              width: 14
                              height: 20
                              rx: 2
                              fill: "=fn.ehzOn() ? '#fca5a5' : '#fee2e2'"
                              stroke: =const.red
                              stroke-width: 1.5
                              style:
                                height: 20px
                                width: 14px
                          - component: f7-row
                            config:
                              tag: path
                              d: M217 205 L227 208 L217 211 L227 214 L217 217 L227 220
                              fill: none
                              stroke: =const.red
                              stroke-width: 1.2
                          - component: f7-row
                            config:
                              comment: Circle KF
                              tag: circle
                              cx: 222
                              cy: 237
                              r: 8
                              fill: "#e4e4e7"
                              stroke: "#71717a"
                              stroke-width: 1.5
                          - component: text
                            config:
                              tag: text
                              x: 222
                              y: 237
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: T
                          - component: f7-row
                            config:
                              comment: Rectangle DFL
                              tag: rect
                              x: 215
                              y: 252
                              rx: 3
                              fill: "#e4e4e7"
                              stroke: "#71717a"
                              stroke-width: 1.5
                              style:
                                height: 14px
                                width: 14px
                          - component: text
                            config:
                              tag: text
                              x: 222
                              y: 259
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: V
                          - component: f7-row
                            config:
                              tag: path
                              d: M212 277 L222 283 L212 289 Z M216 273 L222 283 L228 273 Z M216 293 L222 283 L228 293 Z
                              fill: =const.dark
                          - component: f7-row
                            config:
                              tag: circle
                              cx: 276
                              cy: 275
                              r: 10
                              fill: "=fn.zhpOn() ? const.on : '#facc15'"
                              stroke: =const.dark
                              stroke-width: 1.5
                          - component: f7-row
                            config:
                              tag: path
                              d: M270 280 L276 268 L282 280 Z
                              fill: =const.dark
                          - component: f7-row
                            config:
                              comment: Circle RL
                              tag: circle
                              cx: 276
                              cy: 146
                              r: 8
                              fill: "#e4e4e7"
                              stroke: "#71717a"
                              stroke-width: 1.5
                          - component: text
                            config:
                              tag: text
                              x: 276
                              y: 146
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: T
                          - component: f7-row
                            config:
                              comment: Circle SF
                              tag: circle
                              cx: 108
                              cy: 300
                              r: 8
                              fill: "#e4e4e7"
                              stroke: "#71717a"
                              stroke-width: 1.5
                          - component: text
                            config:
                              tag: text
                              x: 108
                              y: 300
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: T
                          - component: f7-row
                            config:
                              tag: rect
                              x: 336
                              y: 362
                              width: 22
                              height: 52
                              rx: 3
                              fill: url(#wolfcha_saf)
                              stroke: "#71717a"
                              style:
                                height: 52px
                                width: 22px
                          - component: f7-row
                            config:
                              comment: Circle SAF
                              tag: circle
                              cx: 347
                              cy: 352
                              r: 8
                              fill: "#e4e4e7"
                              stroke: "#71717a"
                              stroke-width: 1.5
                          - component: text
                            config:
                              tag: text
                              x: 347
                              y: 352
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: T
                          - component: f7-row
                            config:
                              comment: Rectangle MaxTh
                              tag: rect
                              x: 416
                              y: 117
                              rx: 2
                              fill: "=fn.maxThOn() ? '#fca5a5' : '#e4e4e7'"
                              stroke: "=fn.maxThOn() ? const.red : '#71717a'"
                              stroke-width: 1.5
                              style:
                                height: 15px
                                width: 15px
                          - component: text
                            config:
                              tag: text
                              x: 424
                              y: 124
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: T
                          - component: f7-row
                            config:
                              comment: Circle VF
                              tag: circle
                              cx: 424
                              cy: 155
                              r: 8
                              fill: "#e4e4e7"
                              stroke: "#71717a"
                              stroke-width: 1.5
                          - component: text
                            config:
                              tag: text
                              x: 424
                              y: 155
                              text-anchor: middle
                              dominant-baseline: central
                              font-size: 9
                              font-weight: bold
                              fill: "#52525b"
                              content: T
                          - component: f7-row
                            config:
                              tag: circle
                              cx: 424
                              cy: 187
                              r: 10
                              fill: "=fn.mkpOn() ? const.on : '#facc15'"
                              stroke: =const.dark
                              stroke-width: 1.5
                          - component: f7-row
                            config:
                              tag: path
                              d: M418 192 L424 180 L430 192 Z
                              fill: =const.dark
                          - component: f7-row
                            config:
                              tag: path
                              d: M418 233 L424 243 L430 233 Z M418 253 L424 243 L430 253 Z M434 237 L424 243 L434 249 Z
                              fill: =const.dark
                          - component: f7-row
                            config:
                              tag: circle
                              cx: 408
                              cy: 243
                              r: 7
                              fill: =const.unit
                              stroke: =const.dark
                              stroke-width: 1.5
                    - component: div
                      config:
                        style:
                          position: absolute
                          left: 1%
                          top: 2%
                          font-size: clamp(9px, 2.2vw, 12px)
                          line-height: "1.45"
                          color: gray
                          white-space: nowrap
                      slots:
                        default:
                          - component: Label
                            config:
                              text: ='Außen:\t' + fn.v(props.outsideTemp)
                              style:
                                white-space: pre
                                tab-size: 20
                                line-height: 1.2
                          - component: Label
                            config:
                              text: ='Verdichter:\t' + fn.v(props.compressorFreq)
                              style:
                                color: "=fn.compressorOn() ? 'green' : 'gray'"
                                white-space: pre
                                tab-size: 20
                                line-height: 1.2
                          - component: Label
                            config:
                              text: ='Ventilator:\t' + fn.v(props.fanSpeed)
                              style:
                                white-space: pre
                                tab-size: 20
                                line-height: 1.2
                          - component: Label
                            config:
                              text: ='Leistung:\t' + fn.v(props.power)
                              style:
                                white-space: pre
                                tab-size: 20
                                line-height: 1.2
                    - component: Label
                      config:
                        text: ='RL ' + fn.v(props.returnTemp)
                        style:
                          position: absolute
                          left: 47%
                          top: 40%
                          transform: translateY(-50%)
                          font-size: clamp(9px, 2.2vw, 13px)
                          font-weight: bold
                          white-space: nowrap
                    - component: Label
                      config:
                        text: ='DHK ' + fn.v(props.pressure)
                        style:
                          position: absolute
                          left: 17.5%
                          top: 45.2%
                          transform: translateY(-50%)
                          font-size: clamp(7px, 1vw, 11px)
                          font-weight: bold
                          white-space: nowrap
                    - component: Label
                      config:
                        text: ='KF ' + fn.v(props.boilerTemp)
                        style:
                          position: absolute
                          left: 17.5%
                          top: 56.2%
                          transform: translateY(-50%)
                          font-size: clamp(7px, 2vw, 11px)
                          font-weight: bold
                          white-space: nowrap
                    - component: Label
                      config:
                        text: ='DFL ' + fn.v(props.flowRate)
                        style:
                          position: absolute
                          left: 17.5%
                          top: 61.5%
                          transform: translateY(-50%)
                          font-size: clamp(7px, 2vw, 11px)
                          font-weight: bold
                          white-space: nowrap
                          color: "=fn.flowing() ? 'var(--f7-text-color)' : 'gray'"
                    - component: Label
                      config:
                        text: "='3WUV: \\n' + (fn.ww() ? 'WW' : 'HZ')"
                        style:
                          position: absolute
                          left: 39%
                          top: 69%
                          transform: translateY(-50%)
                          font-size: clamp(8px, 1.8vw, 10px)
                          color: gray
                          white-space: pre-line
                    - component: Label
                      config:
                        text: ZHP
                        style:
                          position: absolute
                          left: 46.8%
                          top: 61.5%
                          transform: translateY(-50%)
                          font-size: clamp(8px, 1.8vw, 10px)
                          color: gray
                    - component: Label
                      config:
                        text: ='SF ' + fn.v(props.dhwTemp)
                        style:
                          position: absolute
                          left: 20%
                          top: 71.4%
                          transform: translateY(-50%)
                          font-size: clamp(9px, 2.2vw, 13px)
                          font-weight: bold
                          white-space: nowrap
                    - component: Label
                      config:
                        text: "='WW: \\n' + fn.v(props.dhwStatus)"
                        style:
                          position: absolute
                          left: 17.5%
                          top: 83%
                          transform: translate(-50%, -50%)
                          font-size: clamp(8px, 1.8vw, 11px)
                          color: "=fn.ww() ? 'red' : 'gray'"
                          white-space: pre-line
                    - component: Label
                      config:
                        text: =fn.v(props.collectorTemp)
                        style:
                          position: absolute
                          left: 56.8%
                          top: 77%
                          transform: translate(-50%, -50%)
                          font-size: clamp(9px, 2.2vw, 13px)
                          font-weight: bold
                          white-space: nowrap
                    - component: Label
                      config:
                        text: ='SAF'
                        style:
                          position: absolute
                          left: 57.8%
                          top: 80%
                          transform: translate(-50%, -50%)
                          font-size: clamp(8px, 1.8vw, 10px)
                          color: gray
                    - component: Label
                      config:
                        text: ='VF ' + fn.v(props.mixerFlowTemp)
                        style:
                          position: absolute
                          left: 72.5%
                          top: 36.9%
                          transform: translateY(-50%)
                          font-size: clamp(9px, 2.2vw, 13px)
                          font-weight: bold
                          white-space: nowrap
                    - component: Label
                      config:
                        text: MaxTh
                        style:
                          position: absolute
                          left: 68%
                          top: 30.2%
                          transform: translate(-100%, -50%)
                          font-size: clamp(8px, 1.8vw, 10px)
                          color: "=fn.maxThOn() ? 'red' : 'gray'"
                    - component: Label
                      config:
                        text: MKP
                        style:
                          position: absolute
                          left: 68.5%
                          top: 44.5%
                          transform: translate(-100%, -50%)
                          font-size: clamp(8px, 1.8vw, 10px)
                          color: gray
                    - component: Label
                      config:
                        text: MM
                        style:
                          position: absolute
                          left: 66%
                          top: 57.9%
                          transform: translate(-100%, -50%)
                          font-size: clamp(8px, 1.8vw, 10px)
                          color: gray
                    - component: Label
                      config:
                        text: "='Mischer: \\n' + fn.v(props.mixerStatus)"
                        visible: =!!props.mixerStatus
                        style:
                          position: absolute
                          left: 57%
                          top: 64%
                          transform: translateY(-50%)
                          font-size: clamp(8px, 1.8vw, 11px)
                          color: gray
                          white-space: pre-line
                    - component: Label
                      config:
                        text: Heizkreis
                        style:
                          position: absolute
                          left: 77.2%
                          top: 13%
                          transform: translate(-50%, -50%)
                          font-size: clamp(8px, 1.8vw, 11px)
                          color: gray


Nice work, a hydraulic schematic is exactly the right view for a heat pump — much easier to read than a row of numbers. One idea for a future version: if you show the day’s thermal energy output next to the electrical input (both easy to derive from persisted power data), users can eyeball an approximate COP at a glance. Including the datapoint numbers in the parameter table already saves a lot of digging, thanks for that.