Home assistant – configuration.yaml

# =========================
# Home Assistant – configuration.yaml
# Uspořádáno, beze změny entit
# =========================

# 1) Základ
default_config:

# 2) Frontend (témata)
frontend:
  themes: !include_dir_merge_named themes

# 3) Logování (poučné pro Modbus ladění)
logger:
  logs:
    homeassistant.components.modbus: debug
    pymodbus.client: debug
    pymodbus.transaction: debug

# 4) Helpery (Inputy, Selecty)
input_number:
  teplotni_setpoint:
    name: Teplotní setpoint
    icon: mdi:thermometer
    min: 10
    max: 50
    step: 0.1
    unit_of_measurement: "°C"
    mode: slider

  hp_heating_water_setpoint:
    name: HP Heating Water Setpoint
    min: 25
    max: 60
    step: 0.5
    unit_of_measurement: "°C"

input_select:
  hp_rezim:
    name: HP režim
    options:
      - Vypnuto
      - Chlazení + TUV
      - Topení + TUV
      - Topení (GCHV)
      - TOPENÍ
      - Eco režim

# 5) Šablony (Template senzory) – sloučeno do jednoho bloku
template:
  - sensor:
      - name: "FV výkon polovina 1"
        unique_id: "pv_power_half_1"
        unit_of_measurement: "W"
        state: >
          {% if states('sensor.deye_sunsynk_sol_ark_3_phase_pv_power_1') | is_number %}
            {{ (states('sensor.deye_sunsynk_sol_ark_3_phase_pv_power_1') | float / 2) | round(1) }}
          {% else %}
            0
          {% endif %}

      - name: "FV výkon polovina 2"
        unique_id: "pv_power_half_2"
        unit_of_measurement: "W"
        state: >
          {% if states('sensor.deye_sunsynk_sol_ark_3_phase_pv_power_1') | is_number %}
            {{ (states('sensor.deye_sunsynk_sol_ark_3_phase_pv_power_1') | float / 2) | round(1) }}
          {% else %}
            0
          {% endif %}
  - sensor:
      # ---- Baterky: průměrný SoC
      - name: "battery_soc_total"
        unique_id: battery_soc_total
        unit_of_measurement: "%"
        device_class: battery
        state: >
          {% set soc1 = states('sensor.2_baterie') | float(0) %}
          {% set soc2 = states('sensor.xiaoxiang_bms_baterie') | float(0) %}
          {% set soc3 = states('sensor.bp00_baterie') | float(0) %}
          {% set soc4 = states('sensor.bp00_baterie_2') | float(0) %}
          {{ ((soc1 + soc2 + soc3 + soc4) / 4) | round(1) }}

      # ---- Baterky: vážený SoC (podle kapacit)
      - name: "battery_soc_totalx"
        unique_id: battery_soc_totalx
        unit_of_measurement: "%"
        device_class: battery
        state: >
          {% set soc1 = states('sensor.2_baterie') | float(0) %}
          {% set soc2 = states('sensor.xiaoxiang_bms_baterie') | float(0) %}
          {% set soc3 = states('sensor.bp00_baterie') | float(0) %}
          {% set soc4 = states('sensor.bp00_baterie_2') | float(0) %}

          {% set cap1 = 7 %}
          {% set cap2 = 7 %}
          {% set cap3 = 14 %}
          {% set cap4 = 17 %}

          {% set total_capacity = cap1 + cap2 + cap3 + cap4 %}
          {% set weighted_sum = soc1 * cap1 + soc2 * cap2 + soc3 * cap3 + soc4 * cap4 %}

          {{ (weighted_sum / total_capacity) | round(1) }}

      # ---- Baterky: celkově uložená energie
      - name: "battery_energy_total"
        unique_id: battery_energy_total
        unit_of_measurement: "Wh"
        device_class: energy
        state_class: measurement
        state: >
          {% set e1 = states('sensor.xiaoxiang_bms_ulozena_energie') | float(0) %}
          {% set e2 = states('sensor.2_ulozena_energie') | float(0) %}
          {% set e3 = states('sensor.bp00_ulozena_energie') | float(0) %}
          {% set e4 = states('sensor.bp00_ulozena_energie_2') | float(0) %}
          {{ (e1 + e2 + e3 + e4) | round(2) }}

      # ---- Ventil: výstup v %
      - name: "Ventil výstup (%)"
        unique_id: ventil_vystup_pct
        unit_of_measurement: "%"
        availability: >
          {{ state_attr('light.shelly0110dimg3_e4b063e6b49c','brightness') is not none }}
        state: >
          {% set bri = state_attr('light.shelly0110dimg3_e4b063e6b49c','brightness') | float(0) %}
          {{ (bri / 255 * 100) | round(1) }}

      # ---- Konstantní setpoint z templatu (ponechán kvůli kompatibilitě)
      - name: "Teplotní setpoint"
        unique_id: teplotni_setpoint
        unit_of_measurement: "°C"
        state: "40"

# 6) Modbus (hub + senzory + přepínače)
modbus:
  - name: hp_9600N1
    type: serial
    method: rtu
    port: /dev/serial/by-id/usb-1a86_USB2.0-Ser_-if00-port0
    baudrate: 9600
    stopbits: 1
    bytesize: 8
    parity: N
    timeout: 5
    retries: 5
    message_wait_milliseconds: 200

    sensors:
      - name: "HP Rezim RAW"
        slave: 11
        address: 44
        input_type: holding
        data_type: uint16
        scan_interval: 5

      - name: "hp_heating_water_setpoint"
        unique_id: "hp_heating_water_setpoint"
        slave: 11
        address: 401
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "°C"
        scan_interval: 10

      - name: "hp_running_mode"
        unique_id: "hp_running_mode"
        slave: 11
        address: 45
        input_type: holding
        data_type: uint16
        scan_interval: 5

      - name: "hp_setting_mode"
        unique_id: "hp_setting_mode"
        slave: 11
        address: 44
        input_type: holding
        data_type: uint16
        scan_interval: 5

      - name: "hp_pump_speed"
        unique_id: "hp_pump_speed"
        slave: 11
        address: 85
        input_type: holding
        data_type: uint16
        unit_of_measurement: "%"
        scan_interval: 10

      - name: "hp_ac_current"
        unique_id: "hp_ac_current"
        slave: 11
        address: 4116
        input_type: holding
        data_type: uint16
        scale: 4
        precision: 1
        unit_of_measurement: "A"
        scan_interval: 10

      - name: "hp_dc_current"
        unique_id: "hp_dc_current"
        slave: 11
        address: 4117
        input_type: holding
        data_type: uint16
        scale: 4
        precision: 1
        unit_of_measurement: "A"
        scan_interval: 10

      - name: "hp_ac_voltage"
        unique_id: "hp_ac_voltage"
        slave: 11
        address: 4118
        input_type: holding
        data_type: uint16
        scale: 2
        precision: 0
        unit_of_measurement: "V"
        scan_interval: 10

      - name: "hp_dc_voltage"
        unique_id: "hp_dc_voltage"
        slave: 11
        address: 4119
        input_type: holding
        data_type: uint16
        scale: 2
        precision: 0
        unit_of_measurement: "V"
        scan_interval: 10

      # --- Nové podle tabulky (foto)
      - name: "hp_compressor_runtime"
        unique_id: "hp_compressor_runtime"
        slave: 11
        address: 372
        input_type: holding
        data_type: uint16
        unit_of_measurement: "h"
        scan_interval: 60

      - name: "hp_pump_runtime"
        unique_id: "hp_pump_runtime"
        slave: 11
        address: 374
        input_type: holding
        data_type: uint16
        unit_of_measurement: "h"
        scan_interval: 60

      - name: "hp_actual_compressor_frequency"
        unique_id: "hp_actual_compressor_frequency"
        slave: 11
        address: 23
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "Hz"
        scan_interval: 10

      - name: "hp_frequency_reduction_mode"
        unique_id: "hp_frequency_reduction_mode"
        slave: 11
        address: 23
        input_type: holding
        data_type: uint16
        scan_interval: 10

      - name: "hp_night_mode"
        unique_id: "hp_night_mode"
        slave: 11
        address: 68
        input_type: holding
        data_type: uint16
        scan_interval: 10

      - name: "hp_outdoor_air_temperature"
        unique_id: "hp_outdoor_air_temperature"
        scan_interval: 10
        address: 1
        slave: 11
        input_type: input
        scale: 0.1
        precision: 1
        device_class: temperature
        unit_of_measurement: "°C"

      - name: "hp_indoor_air_temperature"
        unique_id: "hp_indoor_air_temperature"
        scan_interval: 10
        address: 2
        slave: 11
        input_type: input
        scale: 0.1
        precision: 1
        device_class: temperature
        unit_of_measurement: "°C"

      - name: "hp_entering_water_temperature"
        unique_id: "hp_entering_water_temperature"
        scan_interval: 10
        address: 3
        slave: 11
        input_type: input
        scale: 0.1
        precision: 1
        device_class: temperature
        unit_of_measurement: "°C"

      - name: "hp_leaving_water_temperature"
        unique_id: "hp_leaving_water_temperature"
        scan_interval: 10
        address: 4
        slave: 11
        input_type: input
        scale: 0.1
        precision: 1
        device_class: temperature
        unit_of_measurement: "°C"

      - name: "hp_refrigerant_temperature"
        unique_id: "hp_refrigerant_temperature"
        scan_interval: 10
        address: 5
        slave: 11
        input_type: input
        scale: 0.1
        precision: 1
        device_class: temperature
        unit_of_measurement: "°C"

      - name: "hp_discharge_temperature"
        unique_id: "hp_discharge_temperature"
        scan_interval: 10
        address: 10
        slave: 11
        input_type: input
        scale: 0.1
        precision: 1
        device_class: temperature
        unit_of_measurement: "°C"

      - name: "hp_air_exchanger_temperature"
        unique_id: "hp_air_exchanger_temperature"
        scan_interval: 10
        address: 11
        slave: 11
        input_type: input
        scale: 0.1
        precision: 1
        device_class: temperature
        unit_of_measurement: "°C"

      - name: "hp_heating_setpoint_raw"
        unique_id: "hp_heating_setpoint_raw"
        slave: 11
        address: 421
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "°C"
        scan_interval: 10

    switches:
      - name: "HP Vypnuto"
        slave: 11
        address: 44
        write_type: holding
        command_on: 0
        command_off: 3
        verify:
          input_type: holding
          address: 44
          state_on: 0
          state_off: 3

      - name: "HP Režim Chlazení"
        slave: 11
        address: 44
        write_type: holding
        command_on: 1
        verify:
          input_type: holding
          address: 44
          state_on: 1

      - name: "HP Režim Chlazení + TUV"
        slave: 11
        address: 44
        write_type: holding
        command_on: 2
        verify:
          input_type: holding
          address: 44
          state_on: 2

      - name: "HP Režim Topení + TUV"
        slave: 11
        address: 44
        write_type: holding
        command_on: 3
        verify:
          input_type: holding
          address: 44
          state_on: 3

      - name: "HP Režim Topení (GCHV)"
        slave: 11
        address: 44
        write_type: holding
        command_on: 4
        verify:
          input_type: holding
          address: 44
          state_on: 4

      - name: "HP Režim TUV"
        slave: 11
        address: 44
        write_type: holding
        command_on: 5
        verify:
          input_type: holding
          address: 44
          state_on: 5

# 7) Includy pro automatiky/scény/skripty
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

Zobrazení akumulační nádrže Home Assistant

type: custom:button-card
show_state: false
show_icon: false
show_name: false
tap_action:
  action: none
hold_action:
  action: none
double_tap_action:
  action: none
styles:
  card:
    - padding: 10px
    - border-radius: 16px
    - box-shadow: var(--ha-card-box-shadow)
    - background: var(--card-background-color)
  name:
    - justify-self: center
    - padding-bottom: 30px
  custom_fields:
    svg:
      - width: 100%
      - height: 100%
      - justify-self: center
      - padding: 4px 0 8px 0

custom_fields:
  svg: |
    [[[
      // ==== TVŮJ SEZNAM SENZORŮ SHORA DOLŮ ====
      const sensors = [
        'sensor.shellyplus1_a8032ab6a734_temperature',
        'sensor.shellyplus1_a8032ab6a734_temperature_2',
        'sensor.shellyplus1_a8032ab6a734_temperature_3',
        'sensor.shellyplus1_a8032ab6a734_temperature_5',
        'sensor.shellyplus1_a8032ab6a734_temperature_4',
      ];

      // ==== NAČTENÍ HODNOT ====
      const getState = id => parseFloat(hass.states[id]?.state);
      const temps = sensors.map(getState);
      const safe = v => Number.isFinite(v);

      // ==== BARVA PODLE TEPLOTY ====
      const color = (t) => {
        if (!safe(t)) return '#777';
        let hue, light;

        if (t <= 40) {
          const frac = (t - 20) / 20;
          hue = 240 - 180 * frac; // 240→60 (modrá→žlutá)
          light = 50 + 10 * frac;
        } else if (t <= 50) {
          const frac = (t - 40) / 10;
          hue = 60 - 30 * frac;   // 60→30 (žlutá→oranžová)
          light = 55 - 5 * frac;
        } else if (t <= 60) {
          const frac = (t - 50) / 10;
          hue = 30 - 20 * frac;   // 30→10 (oranžová→světle červená)
          light = 55 + 10 * frac;
        } else {
          const frac = (t - 60) / 20;
          hue = 10 - 10 * frac;   // 10→0 (světle červená→sytě červená)
          light = 65 - 10 * frac; // 65→55
        }
        return `hsl(${hue}, 90%, ${light}%)`;
      };

      // ==== ROZMĚRY A VYKRESLENÍ ====
      const W = 160, H = 340;
      const pad = 14;
      const bodyW = W - 2*pad;
      const capR = 28;
      const yTop = capR;
      const yBottom = H - capR;
      const bodyH = H - 2*capR;
      const bands = temps.length;
      const bandH = bodyH / bands;

      const band = (y, t) =>
        `<rect x="${pad}" y="${y}" width="${bodyW}" height="${bandH}"
               rx="18" ry="18" fill="${color(t)}" />`;

      const label = (y, t) => {
        const txt = safe(t) ? `${t.toFixed(0)}°C` : '–';
        return `<text x="${W/2}" y="${y + bandH/2}"
                      font-size="16" text-anchor="middle"
                      dominant-baseline="middle" fill="#fff"
                      style="paint-order: stroke; stroke: #000; stroke-width: 2px; stroke-linejoin: round;">
                  ${txt}
                </text>`;
      };

      const outline = `
        <ellipse cx="${W/2}" cy="${yTop}"    rx="${bodyW/2}" ry="${capR}" fill="none" stroke="#444" stroke-width="3"/>
        <rect    x="${pad}"  y="${yTop}"      width="${bodyW}" height="${bodyH}" fill="none" stroke="#444" stroke-width="3"/>
        <ellipse cx="${W/2}" cy="${yBottom}" rx="${bodyW/2}" ry="${capR}" fill="none" stroke="#444" stroke-width="3"/>
      `;

      let bandsSvg = '', labelsSvg = '';
      for (let i = 0; i < bands; i++) {
        const y = yTop + i * bandH;
        bandsSvg  += band(y, temps[i]);
        labelsSvg += label(y, temps[i]);
      }

      return `<svg viewBox="0 0 ${W} ${H}" width="100%" height="100%">
        ${bandsSvg}
        ${outline}
        ${labelsSvg}
      </svg>`;
    ]]]