---
substitutions:
  device: heater
  name: Heater
  area: Basement
  comment: Hot water and Heating control

esphome:
  name: mcu-${device}
  friendly_name: ${name}
  area: ${area}
  comment: ${comment}
  areas:
    - id: local_area
      name: ${area}
  devices:
    - id: heating
      name: Heating
      area_id: local_area
    - id: hot_water
      name: Hot Water
      area_id: local_area

esp32:
  variant: esp32
  toolchain: esp-idf
  framework:
    type: esp-idf

external_components:
  # - source: github://pr#12717
  #   components: [ds248x]
  #   refresh: 1h
  - source: github://pr#13534
    components: [ds2482, ds2484, ds248x_base]
    refresh: 1h

packages:
  common: !include common/common.yaml

# PINOUTS: M5ATOM
# IR        G12
# NEO       G27
# BUTTON    G39
# I2C0 SDA  G26
# I2C0 SCL  G32
# I2C1 SDA  G25
# I2C1 SCL  G21
# UART0 RX  G3
# UART0 TX  G1
# UART1 RX  G23
# UART1 TX  G33
# 1-WIRE    G22
# NC        G19

#logger:
#  level: VERBOSE
#  logs:
#    dallas.component: ERROR
#    uart.component: ERROR
#    i2c.component: VERBOSE

# Heating / Hot water Controller
# temp_1: Solar Collector
# temp_2: Cylinder Bottom (solar)
# temp_3: Cylinder Top (heater)
# temp_4: Heating OUT
# temp_5: Heating IN
# relay_1: Solar Pump
# relay_2: Hot Water Heating Demand
# relay_3: Heating Demand
# input_1: Off Peak Status
# input_2: Heating Thermostat Demand Overrride
# temp_1_delta: delta temperature (= temp_2 - temp_1)
# temp_2_set: requested temp_2
# temp_3_set: requested temp_3
# temp_3_delta: delta for temp_3
#
## RULES
## - Hot Water Solar
# if ((temp_1 - temp_1_delta) < temp_2_set) && ((temp_2 - temp_1) > temp_1_delta) then relay_1 ON  <<< WTF?
# if (temp_2 > temp_2_set) || ((temp_1_delta / 2) > (temp_2 - temp_1)) then relay_1 OFF
# The controller running this mode compares four values: source temperature at sensor A (Ta), sink temperature at sensor B (Tb), target point (Tstop) temperature and minimal starting (Tstart) temperature as follows.
# The controller will switch relay output on, and will show Î (black triangle up) next to relay output status, when all the following three conditions are satisfied:
# •source temperature TA is greater or equal minimal starting Tst ar t temperature,
# • sink temperature TB is less that target Tstop temperature, and
# •the difference between source temperature Ta and sink temperature Tb , i.e. Ta − Tb , is above or equal to ∆ON degrees.
# When the difference Ta − Tb falls below or is equal to ∆OFF degrees (the last criterion is not satisfied), the controller displays È (black triangle down) and switches relay output off.
# Furthermore, if temperature Tb reaches target point temperature, i.e. Tb ≥ Tstop , then the controller displays Tm and the relay switches off. When temperature Tb falls below Tstop for 42 degrees, status of output relay depends on temperature Ta as described in this paragraph.
# When the starting temperature has not been reached, the controller displays a negative value, i.e. the difference Tstart − Ta, that is the difference between source and starting temperature.
# Note, that relay response might be delayed due to relay delay protection.
# Turn on ∆ON and turn off ∆OFF difference Values of ∆ON and ∆OFF are derived from 41 and 42 as minimum and maximum. For instance, if 41 < 42, then ∆OFF = 41 and ∆ON = 42. When 41 = 42, then 41 and 42 are adapted, eg. 41 lowers for 0.5 degrees and 42 increases for 0.5 degrees.
# Solar thermocouplers KTY83 https://www.nxp.com/docs/en/data-sheet/KTY83_SER.pdf / regultor by https://www.duel-ltd.sk
# 1303 kOhm -> 57.9 C
#
## - Hot Water Heater / Heating
# set desired temperature - Day / Night + Schedule for normall day and weekend
# real room temperature - based on one of rooms, or based on coldest room
# very simple - if temp lower, start heater / hot water demand

globals:
  - id: temp_1 # Heating
    type: float
    restore_value: no
    initial_value: '12.0'
  - id: set_hot_water_solar_delta # Solar Collector
    type: float
    restore_value: no
    initial_value: '10.0'
  - id: set_hot_water_solar_temperature # Cylinder Bottom (solar)
    type: float
    restore_value: no
    initial_value: '70.0'
  - id: set_hot_water_heating_temperature_min # Cylinder Top (heater)
    type: float
    restore_value: no
    initial_value: '40.0'
  - id: set_hot_water_heating_temperature_max # Cylinder Top (heater)
    type: float
    restore_value: no
    initial_value: '50.0'
  - id: set_heating_temperature_min # Heating
    type: float
    restore_value: no
    initial_value: '19.0'
  - id: set_heating_temperature_max # Heating
    type: float
    restore_value: no
    initial_value: '20.5'

time:
  - platform: homeassistant
    id: ha_time
    timezone: Europe/Bratislava
    on_time:
      - seconds: 0
        minutes: /1
        # hours: 5-23
        # days_of_week: MON-FRI
        then:
          lambda: |-
            if (id(hot_water_heater).state >= 67.0) {
              id(hot_water_demand).turn_off();
            }

climate:
  - platform: bang_bang
    sensor: hot_water_heater
    name: ""
    id: hot_water_climate
    device_id: hot_water
    visual:
      min_temperature: 40
      max_temperature: 65
      temperature_step: 1
      # temperature_step: 0.1 °C
    default_target_temperature_low: 48 °C
    default_target_temperature_high: 56 °C
    heat_action:
      - switch.turn_on: hot_water_demand
    idle_action:
      - switch.turn_off: hot_water_demand
    away_config:
      default_target_temperature_low: 30 °C
      default_target_temperature_high: 40 °C

i2c:
  # - id: i2c0
  # sda: 26
  # scl: 32
  # scan: true #false
  # - id: i2c1
  sda: 25
  scl: 21
  scan: true #false

# one_wire:
#   id: one_wire_bus
#   # i2c_id: i2c_main
#   platform: ds2484
#   active_pullup: true

# ds248x:
#   id: ds2484_module
#   address: 0x18
#   active_pullup: true

# one_wire:
#   - platform: ds248x
#     ds248x_id: ds2484_module
#     id: one_wire_bus

one_wire:
  id: one_wire_bus
  # i2c_id: i2c_main
  platform: ds2482
  active_pullup: true

modbus:
  uart_id: uart_modbus

uart:
  - id: uart_modbus
    rx_pin: 23
    tx_pin: 33
    baud_rate: 9600
    stop_bits: 2
    # debug:

pca9554:
  - id: pca9554_module
    address: 0x27

switch:
  - platform: template
    name: Heating Enabled
    id: heating_enabled
    device_id: heating
    optimistic: True
  - platform: gpio
    name: Demand # Hot Water Heating Demand (to Heater)
    id: hot_water_demand
    device_id: hot_water
    pin: 22
    inverted: true
  - platform: gpio
    name: Demand # Heating Demand (to Heater)
    id: heating_demand
    device_id: heating
    pin: 19
    inverted: true
  - platform: gpio
    name: Power Level II
    id: heating_power_level_2
    pin:
      pca9554: pca9554_module
      number: 4
  - platform: gpio
    name: Power Level III
    id: heating_power_level_3
    pin:
      pca9554: pca9554_module
      number: 5
# - platform: uart
#     name: Total Heater Power Reset
#     uart_id:
#     id: reset_total_heater_power
#     data: [0x01, 0x42, 0x80, 0x11]

sensor:
  # - platform: ds248x
  - platform: dallas_temp
    # [22:06:25][D][dallas.sensor:082]:     0x1701143E35C5AA28  Feed
    # [22:06:25][D][dallas.sensor:082]:     0x7301143F7F57AA28  Return
    # [22:06:25][D][dallas.sensor:082]:     0xF701143E397FAA28  Heater Tank
    # [22:06:25][D][dallas.sensor:082]:     0x5A041750B2C8FF28  Hot Water Tank - Bottom (Solar)
    # [22:06:25][D][dallas.sensor:082]:     0xDB041750EAE2FF28  Heating Water Return (OUT from System, TO Heater)
    # [22:06:25][D][dallas.sensor:082]:     0xB2041750CF1AFF28  Heating Water (OUT from Heater, TO System)
    # [22:06:25][D][dallas.sensor:082]:     0x960417517301FF28  Hot Water Tank - TOP (Heater)
    # address: 0x320417500A93FF28 # 1. broken
    # address: 0x67041750F44CFF28 # 2. broken
    address: 0x960417517301FF28 # Hot Water Tank - TOP (Heater)
    name: Heater
    id: hot_water_heater
    device_id: hot_water
  # - platform: ds248x
  - platform: dallas_temp
    address: 0x5A041750B2C8FF28 # Hot Water Tank - Bottom (Solar)
    name: Solar
    id: hot_water_solar
    device_id: hot_water
  # - platform: ds248x
  - platform: dallas_temp
    address: 0xF701143E397FAA28 # Heater Tank
    name: Temperature
    id: heater
  # - platform: ds248x
  - platform: dallas_temp
    address: 0x1701143E35C5AA28 # Heating Water Feed (OUT from Heater, TO System)
    name: OUT2
    id: heating_out
    device_id: heating
  # - platform: ds248x
  - platform: dallas_temp
    address: 0x7301143F7F57AA28 # Heating Water Return (OUT from System, TO Heater)
    name: IN2
    id: heating_in
    device_id: heating
  # - platform: template
  #   name: Total Daily Energy
  #   id: heater_daily_energy
  #   lambda: |-
  #     return (id(heater_l1_total_daily_energy).state + id(heater_l3_total_daily_energy).state + id(heater_l3_total_daily_energy).state);
    update_interval: 60s
  - platform: template
    name: Daily Energy Price
    id: heater_energy_price
    unit_of_measurement: '€'
    lambda: |-
      //# platba za odberne miesto        0,75          1,1
      //# pevna mesacna zlozka tarify     0,15080000    0,1508 * 75 A

      //## platba za systemove sluzby      0,00629760
      //# platba za prevadzku systemu     0,01590000
      //# variabilna zlozka tarify za distribuciu 0,00398400
      //# platba za straty elktr.sidtr.el.        0,01146600
      //# odvod do jadroveho fondu        0,00327000
      //#
      //# cena za elektrinu VT    0,06390000            0,10380000
      //# cena za elektrinu NT    0,04110000            0,06900000
      //# 0.00594340+0.02598800+0.00279200+0.00687300+0.00327000+0.04110000 = 0.0859664
      //# prenos mesacne = 0,15080000*75
      //# prenos spotreba * (0,00398400+0,01146600+0,00327000+0,00629760+0,01590000) = spotreba * 0,0409176

      // # 1,1 + (VT * 0,1038) + (NT * 0,069) + (75 * 0,1508) + ((VT+NT) * (0,00398400+0,01146600+0,00327000+0,00629760+0,01590000))
      return (id(heater_total_daily_energy).state * (0.0409176 + 0.069));
  # L1
  - platform: pzemac
    #address: 161
    current:
      name: L1 Current
    voltage:
      name: L1 Voltage
    energy:
      name: L1 Energy
      id: heater_l1_energy
    power:
      name: L1 Power
      id: heater_l1_power
    frequency:
      name: L1 Frequency
    power_factor:
      name: L1 Power Factor
    update_interval: 20s
  - platform: total_daily_energy
    name: L1 Total Daily Energy
    power_id: heater_l1_power
    id: heater_l1_total_daily_energy
    filters:
      - multiply: 0.001
    unit_of_measurement: kWh
    icon: mdi:counter
  - platform: integration
    name: L1 Energy Meter"
    sensor: heater_l1_power
    time_unit: h
    filters:
      - lambda: return x * (0.001) + 2282;
    unit_of_measurement: kWh
    icon: mdi:counter
  # L2
  - platform: pzemac
    address: 162
    current:
      name: L2 Current
    voltage:
      name: L2 Voltage
    energy:
      name: L2 Energy
      id: heater_l2_energy
    power:
      name: L2 Power
      id: heater_l2_power
    frequency:
      name: L2 Frequency
    power_factor:
      name: L2 Power Factor
    update_interval: 20s
  - platform: total_daily_energy
    name: L2 Total Daily Energy
    id: heater_l2_total_daily_energy
    power_id: heater_l2_power
    filters:
      - multiply: 0.001
    unit_of_measurement: kWh
    icon: mdi:counter
  - platform: integration
    name: L2 Energy Meter
    sensor: heater_l2_power
    time_unit: h
    filters:
      - lambda: return x * (0.001) + 2282;
    unit_of_measurement: kWh
    icon: mdi:counter
  # L3
  - platform: pzemac
    address: 163
    current:
      name: L3 Current
    voltage:
      name: L3 Voltage
    energy:
      name: L3 Energy
      id: heater_l3_energy
    power:
      name: L3 Power
      id: heater_l3_power
    frequency:
      name: L3 Frequency
    power_factor:
      name: L3 Power Factor
    update_interval: 20s
  - platform: total_daily_energy
    name: L3 Total Daily Energy
    power_id: heater_l3_power
    id: heater_l3_total_daily_energy
    filters:
      - multiply: 0.001
    unit_of_measurement: kWh
    icon: mdi:counter
  - platform: integration
    name: L3 Energy Meter
    sensor: heater_l3_power
    time_unit: h
    filters:
      - lambda: return x * (0.001) + 2282;
    unit_of_measurement: kWh
    icon: mdi:counter
  # TOTAL: L1+L2+L3
  - platform: template
    name: Power
    id: total_heater_power
    device_class: power
    state_class: measurement
    unit_of_measurement: W
    accuracy_decimals: 1
    lambda: |-
      return id(heater_l1_power).state + id(heater_l2_power).state + id(heater_l3_power).state ;
  - platform: template
    name: Total Daily Energy
    id: heater_total_daily_energy
    icon: mdi:counter
    device_class: energy
    # state_class: measurement
    state_class: total_increasing
    unit_of_measurement: kWh
    accuracy_decimals: 1
    lambda: |-
      return id(heater_l1_total_daily_energy).state + id(heater_l2_total_daily_energy).state + id(heater_l3_total_daily_energy).state ;
  - platform: template
    name: Energy
    icon: mdi:counter
    device_class: energy
    state_class: total_increasing
    unit_of_measurement: kWh
    accuracy_decimals: 1
    filters:
      - multiply: 0.001
    lambda: |-
      return id(heater_l1_energy).state + id(heater_l2_energy).state + id(heater_l3_energy).state ;

binary_sensor:
  - platform: gpio
    name: Off Peak # Off Peak (HDO)
    id: off_peak_status
    pin:
      pca9554: pca9554_module
      number: 0
    filters:
      - delayed_on: 300ms
      - delayed_off: 300ms
  - platform: gpio
    name: "ON" # Heater ON
    id: heater_on
    pin:
      pca9554: pca9554_module
      number: 1
    filters:
      - delayed_on: 300ms
      - delayed_off: 300ms
  - platform: gpio
    name: Error
    id: heating_error
    pin:
      pca9554: pca9554_module
      number: 2
    filters:
      - delayed_on: 300ms
      - delayed_off: 300ms
  - platform: template
    id: heater_alarm
    name: Alarm
    lambda: |-
      if (id(off_peak_status).state && (id(heating_demand).state || id(heating_power_level_2).state) && !id(heater_on).state) {
        return true;
      } else {
        return false;
      }
  - platform: homeassistant
    id: trv_heating_demand
    entity_id: binary_sensor.trv_heating_demand
    device_id: heating
  - platform: homeassistant
    id: heating_fireplace_fire
    entity_id: binary_sensor.heating_fireplace_fire
    device_id: heating
  - platform: template
    id: request_heating_demand
    name: Request Demand
    device_id: heating
    lambda: |-
      if (id(trv_heating_demand).state && id(heating_enabled).state && !id(heating_fireplace_fire).state) {
        return true;
      } else {
        return false;
      }
    on_press:
      then:
        - switch.turn_on: heating_demand
    on_release:
      then:
        - switch.turn_off: heating_demand
