Modbus switch - write specific bit in holding register

Hi all smart people!

Does it have to be this complicated to create Modbus switches, where each switch is a bit in a register, or is there an easier way?

modbus:
  - name: heru
    type: tcp
    host: !secret heru_ip
    port: 10502
    sensors: !include modbus/heru_sensors.yaml
    binary_sensors: !include modbus/heru_binary_sensors.yaml
    switches: !include modbus/heru_switches.yaml
# modbus/heru_sensors.yaml

- name: TPHeruAlarmRelayOutput
# 0=Off, 1=On
# Bit mask:
# bit 0: Fire
# bit 1: Sensor open
# bit 2: Sensor shorted
# bit 3: Overheat protection
# bit 4: Freeze alarm
# bit 5: Supply temperature low
# bit 6: Rotor temperature low
# bit 7: Fan failure
# bit 8: Heat exchanger
# bit 9: Duct pressure deviation
# bit 10: Pump alarm
# bit 11: Filter
# bit 12: Filter timer
  slave: 1
  address: 45
  input_type: holding
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15
# configuration.yaml

switch:
  - platform: template
    switches:
      herufirealarmrelayoutput:
        value_template: "{{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(1) > 0 }}"
        turn_on:
          - service: modbus.write_register
            data:
              hub: heru
              unit: 1
              address: 45
              value: >
                {% set reg = states.sensor.tpherualarmrelayoutput.state | int(default=0) %}
                {% set bit = 1 %}
                {{ reg | bitwise_or(2 ** (bit - 1)) }}
          - service: homeassistant.update_entity
            data:
              entity_id: sensor.tpherualarmrelayoutput
        turn_off:
          - service: modbus.write_register
            data:
              hub: heru
              unit: 1
              address: 45
              value: >
                {% set reg = states.sensor.tpherualarmrelayoutput.state | int(default=0) %}
                {% set bit = 1 %}
                {{ reg | bitwise_and(65535 - (2 ** (bit - 1))) }}
          - service: homeassistant.update_entity
            data:
              entity_id: sensor.tpherualarmrelayoutput

It would have been nice if you could solve it in a way similar to this, but I guess it’s not possible:

# modbus/heru_switches.yaml

- name: HeruFireAlarmRelayOutput
  slave: 1
  address: 45
  write_type: holding
  command_on: bit1, on    <-- Something like this.
  command_off: bit1, off  <-- Something like this. 
  scan_interval: 15
  verify:
    input_type: holding
    address: 45
    state_on:  bit1, on    <-- Something like this.
    state_off:  bii1, off  <-- Something like this.
2 Likes

Found a slightly nicer solution that I thought I would share.
I found this way to make the template switch a little nicer with the help of a script that can be used for all my template switches by calling the script as a service.

script:
  write_register_turn_on_bit:
    sequence:
      - service: modbus.write_register
        data:
          hub: "{{ hub }}"
          unit: "{{ unit }}"
          address: "{{ address }}"
          value: "{{ states(sensor_value) | int(default=0) | bitwise_or(2 ** (bit | int - 1)) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: "{{ sensor_value }}"

  write_register_turn_off_bit:
    sequence:
      - service: modbus.write_register
        data:
          hub: "{{ hub }}"
          unit: "{{ unit }}"
          address: "{{ address }}"
          value: "{{ states(sensor_value) | int(default=0) | bitwise_and(65535 - (2 ** (bit | int - 1))) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: "{{ sensor_value }}"

This is how I configured the template switch. This way all I need to change between the 16 “bit switches” in this registry ('sensor.modbus_holding_register') are the bit position and the name of the switch.

switch:
  - platform: template
    switches:
      Fire_alarm_relay_output:
        value_template: >
          {% set bit = 1 %}
          {{ states('sensor.modbus_holding_register') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 1
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.modbus_holding_register
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 1
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.modbus_holding_register
1 Like

Hey

I’m assuming this is for an Östberg Heru ventilation unit. How does it work for you and how happy are you with this solution? Im also looking for a solution to integrate my Heru to HA. any advice will be highly appreciated.

Thank you
Wael

Continuing the discussion from Modbus switch - write specific bit in holding register:

Hello!

Yes it is an Östberg Heru Energy Recovery Unit model 100 S EC -V1.
My plan with the integration was to make a replica of the IQ remote control in Home Assistant UI but I’m not finished with the Lovelace layout yet.

This is what I have so far :slight_smile:
.
.
heru_binary_sensors.yaml

- name: HeruFireAlarmInput
  slave: 1
  address: 0
  input_type: discrete_input
  scan_interval: 15

- name: HeruBoostInput
  slave: 1
  address: 1
  input_type: discrete_input
  scan_interval: 15

- name: HeruOverpressureInput
  slave: 1
  address: 2
  input_type: discrete_input
  scan_interval: 15

- name: HeruExtendedOperationInput
  slave: 1
  address: 3
  input_type: discrete_input
  scan_interval: 15

- name: HeruAwayInput
  slave: 1
  address: 4
  input_type: discrete_input
  scan_interval: 15

- name: HeruFilterInput
  slave: 1
  address: 5
  input_type: discrete_input
  scan_interval: 15

- name: HeruHeaterInterlock
  slave: 1
  address: 6
  input_type: discrete_input
  scan_interval: 15

- name: HeruFireAlarm
  slave: 1
  address: 9
  input_type: discrete_input
  scan_interval: 15

- name: HeruRotorAlarm
  slave: 1
  address: 10
  input_type: discrete_input
  scan_interval: 15

- name: HeruFreezeAlarm
  slave: 1
  address: 12
  input_type: discrete_input
  scan_interval: 15

- name: HeruLowSupplyAlarm
  slave: 1
  address: 13
  input_type: discrete_input
  scan_interval: 15

- name: HeruLowRotorTempAlarm
  slave: 1
  address: 14
  input_type: discrete_input
  scan_interval: 15

- name: HeruTempSensorOpenCircuitAlarm
  slave: 1
  address: 17
  input_type: discrete_input
  scan_interval: 15

- name: HeruTempSensorShortCircuitAlarm
  slave: 1
  address: 18
  input_type: discrete_input
  scan_interval: 15

- name: HeruPulserAlarm
  slave: 1
  address: 19
  input_type: discrete_input
  scan_interval: 15

- name: HeruSupplyFanAlarm
  slave: 1
  address: 20
  input_type: discrete_input
  scan_interval: 15

- name: HeruExhaustFanAlarm
  slave: 1
  address: 21
  input_type: discrete_input
  scan_interval: 15

- name: HeruSupplyFilterAlarm
  slave: 1
  address: 22
  input_type: discrete_input
  scan_interval: 15

- name: HeruExhaustFilterAlarm
  slave: 1
  address: 23
  input_type: discrete_input
  scan_interval: 15

- name: HeruFilterTimerAlarm
  slave: 1
  address: 24
  input_type: discrete_input
  scan_interval: 15

- name: HeruFreezeProtectionBlevel
  slave: 1
  address: 25
  input_type: discrete_input
  scan_interval: 15

- name: HeruFreezeProtectionAlevel
  slave: 1
  address: 26
  input_type: discrete_input
  scan_interval: 15

- name: HeruStartup1stPhase
  slave: 1
  address: 27
  input_type: discrete_input
  scan_interval: 15

- name: HeruStartup2stPhase
  slave: 1
  address: 28
  input_type: discrete_input
  scan_interval: 15

- name: HeruHeating
  slave: 1
  address: 29
  input_type: discrete_input
  scan_interval: 15

- name: HeruRecoveryHeatCold
  slave: 1
  address: 30
  input_type: discrete_input
  scan_interval: 15

- name: HeruCooling
  slave: 1
  address: 31
  input_type: discrete_input
  scan_interval: 15

- name: HeruCO2boost
  slave: 1
  address: 32
  input_type: discrete_input
  scan_interval: 15

- name: HeruRHboost
  slave: 1
  address: 33
  input_type: discrete_input
  scan_interval: 15

- name: HeruHeatingPumpAlarm
  slave: 1
  address: 34
  input_type: discrete_input
  scan_interval: 15

- name: HeruCoolingPumpAlarm
  slave: 1
  address: 35
  input_type: discrete_input
  scan_interval: 15

.
.
.
heru_sensors.yaml

- name: HeruOutdoorTemp
  slave: 1
  address: 1
  input_type: input
  unit_of_measurement: '°C'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruSupplyAirTemp
  slave: 1
  address: 2
  input_type: input
  unit_of_measurement: '°C'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruExtractAirTemp
  slave: 1
  address: 3
  input_type: input
  unit_of_measurement: '°C'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruExhaustAirTemp
  slave: 1
  address: 4
  input_type: input
  unit_of_measurement: '°C'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruWaterTemp
  slave: 1
  address: 5
  input_type: input
  unit_of_measurement: '°C'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruHeatRecoveryTemp
  slave: 1
  address: 6
  input_type: input
  unit_of_measurement: '°C'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruRoomTemp
  slave: 1
  address: 7
  input_type: input
  unit_of_measurement: '°C'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruSupplyPressure
  slave: 1
  address: 11
  input_type: input
  unit_of_measurement: 'Pa'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruExtractPressure
  slave: 1
  address: 12
  input_type: input
  unit_of_measurement: 'Pa'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: TPHeruSensorsOpen
# Bit mask. Bit is set if sensor is required and open circuit. See also Sensors shorted.
  slave: 1
  address: 17
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruSensorsShorten
# Bit mask. Bit is set if sensor is required and shorten. Bit0 = T1 ... Bit6 = T7.
  slave: 1
  address: 18
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruFilterDaysLeft
  slave: 1
  address: 19
  input_type: input
  unit_of_measurement: 'days'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruCurrentWeektimerProgram
# 0 = none, 1-5 = program 1-5
  slave: 1
  address: 20
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruCurrentSupplyFanStep
# 0 = Off, 1 = Min, 2 = Std, 3 = Max
  slave: 1
  address: 22
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruCurrentExhaustFanStep
# 0 = Off, 1 = Min, 2 = Std, 3 = Max
  slave: 1
  address: 23
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruCurrentSupplyFanPower
  slave: 1
  address: 24
  input_type: input
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruCurrentExhaustFanPower
  slave: 1
  address: 25
  input_type: input
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruCurrentSupplyFanSpeed
  slave: 1
  address: 26
  input_type: input
  unit_of_measurement: 'rpm'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruCurrentExhaustFanSpeed
  slave: 1
  address: 27
  input_type: input
  unit_of_measurement: 'rpm'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruCurrentHeatingPower
# In range 0-255. Heater rated power: 1200W
  slave: 1
  address: 28
  input_type: input
  unit_of_measurement: 'W'
  count: 1
  scale: 4.706 # 1200/255=4.706
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruCurrentHeatColdRecoveryPower
# In range 0-255
  slave: 1
  address: 29
  input_type: input
#  unit_of_measurement: 'W'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruCurrentCoolingPower
# In range 0-255
  slave: 1
  address: 30
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSupplyFanControlVoltage
  slave: 1
  address: 31
  input_type: input
  unit_of_measurement: 'V'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruExhaustFanControlVoltage
  slave: 1
  address: 32
  input_type: input
  unit_of_measurement: 'V'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: TPHeruQualitySensor1_type
# 0 = None, 1 = RH, 2 = CO2, 3 = VOC
  slave: 1
  address: 40
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruQualitySensor1_value
# RH: 0-10V=0-100(%), CO2: 0-10V=0-2000(PPM), VOC: 0-10V=0-2000(PPM)
  slave: 1
  address: 41
  input_type: input
#  unit_of_measurement: '%'
#  unit_of_measurement: RPM
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruQualitySensor2_type
# 0 = None, 1 = RH, 2 = CO2, 3 = VOC
  slave: 1
  address: 42
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruQualitySensor2_value
# RH: 0-10V=0-100(%), CO2: 0-10V=0-2000(PPM), VOC: 0-10V=0-2000(PPM)
  slave: 1
  address: 43
  input_type: input
#  unit_of_measurement: '%'
#  unit_of_measurement: RPM
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruQualitySensor3_type
# 0 = None, 1 = RH, 2 = CO2, 3 = VOC
  slave: 1
  address: 44
  input_type: input
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruQualitySensor3_value
# RH: 0-10V=0-100(%), CO2: 0-10V=0-2000(PPM), VOC: 0-10V=0-2000(PPM)
  slave: 1
  address: 45
  input_type: input
#  unit_of_measurement: '%'
#  unit_of_measurement: RPM
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruTempSetpointEconomy
# 15-39°C
  slave: 1
  address: 0
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruTempSetpoint
# 15-40°C
  slave: 1
  address: 1
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSupplyFanSpeed
# 0-100%
  slave: 1
  address: 2
  input_type: holding
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruExhaustFanSpeed
# 0-100%
  slave: 1
  address: 3
  input_type: holding
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruMinSupplyFanSpeed
# 0-100%
  slave: 1
  address: 4
  input_type: holding
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruMaxSupplyFanSpeed
# 0-100%
  slave: 1
  address: 5
  input_type: holding
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruRegulationMode
# 0 = Supply, 1 = Extract, 2 = Room, 3 = Extract S/W, 4 = Room S/W
  slave: 1
  address: 11
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruMinSupplyTemp
# 15-19°C
  slave: 1
  address: 12
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruMaxSupplyTemp
# 20-40°C
  slave: 1
  address: 13
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSupplyColdLimitA
# 2-10°C
  slave: 1
  address: 14
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSupplyColdLimitB
# 5-12°C
  slave: 1
  address: 15
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruFreezeProtectionLimitTemp
# 5-10°C
  slave: 1
  address: 16
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruSNCenabled
# 0 = no, 1 = yes
  slave: 1
  address: 18
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSNCindoorOutdoorDiffLimit
# 10-100°C
  slave: 1
  address: 19
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 1
  data_type: int16
  scan_interval: 15

- name: HeruSNCexhaustHighLimit
# 18-24°C
  slave: 1
  address: 20
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSNCexhaustLowLimit
# 19-26°C
  slave: 1
  address: 21
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruStandbyTempEvaluationEnabled
# 0 = no, 1 = yes
  slave: 1
  address: 22
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSNCstandbyTempEvalInterval
# 1-4 hours
  slave: 1
  address: 23
  input_type: holding
  unit_of_measurement: 'h'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSNCstandbyEvalTime
# 5-15 min
  slave: 1
  address: 24
  input_type: holding
  unit_of_measurement: 'min'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSNCminOperatingTime
# 30-120 min
  slave: 1
  address: 25
  input_type: holding
  unit_of_measurement: 'min'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruBoostDuration
# 10-240min
  slave: 1
  address: 26
  input_type: holding
  unit_of_measurement: 'min'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruOverpressureDuration
# 10-60min
  slave: 1
  address: 27
  input_type: holding
  unit_of_measurement: 'min'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruOverpressureOffset
# 5 - Max value of diff. between EC Min and EC Max
  slave: 1
  address: 28
  input_type: holding
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruFireSensorType
# 0: None, 1: Normally open (NO), 2: Normally closed (NC)
  slave: 1
  address: 29
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruFireMode
# 0: Fans off, 1: Exhaust fan only, 2: Supply fan only, 3: Both fans
  slave: 1
  address: 30
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruForcedFanspeed
# 0 - 100% (Only used when 4x00031 > 0)
  slave: 1
  address: 31
  input_type: holding
  unit_of_measurement: '%'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruSupplyPressureSensorType
# 0 = None, 1 = 0..100 Pa, 2 = 0..200 Pa, 3 = 0..300 Pa, 4 = 0..500 Pa, 5 = 0..700 Pa, 6 = 0..1000 Pa, 7 = 0..1250 Pa, 8 = 0..1500 Pa, 9 = 0..2000 Pa, 10 = 0..2500 Pa
  slave: 1
  address: 32
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruExhaustPressureSensorType
# 0 = None, 1 = 0..100 Pa, 2 = 0..200 Pa, 3 = 0..300 Pa, 4 = 0..500 Pa, 5 = 0..700 Pa, 6 = 0..1000 Pa, 7 = 0..1250 Pa, 8 = 0..1500 Pa, 9 = 0..2000 Pa, 10 = 0..2500 Pa
  slave: 1
  address: 33
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruFilterMeasurementWeekday
# 0 = Monday, 1 = Tuesday ... 6 = Sunday
  slave: 1
  address: 36
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruFilterMeasurementHour
# 0-23 hour
  slave: 1
  address: 37
  input_type: holding
  unit_of_measurement: 'h'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruFilterMeasurementMinute
# 0-59 min
  slave: 1
  address: 38
  input_type: holding
  unit_of_measurement: 'min'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruFilterSpeedIncrease
# 5 to 50 = allowed power increase in %-units. Writing 5 or less equals 5
  slave: 1
  address: 39
  input_type: holding
  unit_of_measurement: '%pts'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruFilterMeasurementMode
# 0 = Off, 1 = Switch, 2 = Speed inc., 3 = Differential
  slave: 1
  address: 40
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruFilterChangePeriod
# 6-12 month. Filter timer in months. 0 = off, 6-12 time in months (30 days). Writing 5 or less equals 6
  slave: 1
  address: 43
  input_type: holding
  unit_of_measurement: 'month'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruAlarmClasses
# 0=A, 1=B
# Bit mask:
# bit 0: - Not used -
# bit 1: Sensor open
# bit 2: Sensor shorted
# bit 3: Overheat protection
# bit 4: Freeze alarm
# bit 5: Supply temperature low
# bit 6: Rotor temperature low
# bit 7: Fan failure
# bit 8: Heat exchanger
# bit 9: Duct pressure deviation
# bit 10: Pump alarm
# bit 11: - Not used -
# bit 12: - Not used -
  slave: 1
  address: 44
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruAlarmRelayOutput
# 0=Off, 1=On
# Bit mask:
# bit 0: Fire
# bit 1: Sensor open
# bit 2: Sensor shorted
# bit 3: Overheat protection
# bit 4: Freeze alarm
# bit 5: Supply temperature low
# bit 6: Rotor temperature low
# bit 7: Fan failure
# bit 8: Heat exchanger
# bit 9: Duct pressure deviation
# bit 10: Pump alarm
# bit 11: Filter
# bit 12: Filter timer
  slave: 1
  address: 45
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 5

- name: TPHeruAlarmRelayContactFunction
# 0=NO, 1=NC
# Bit mask:
# bit 0: A-relay state
# bit 1: B-relay state
# bit 2: Run-relay state
  slave: 1
  address: 46
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSetpointMaxLimitComfort
# 15-40°C
  slave: 1
  address: 47
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruEcoSetpointEnabled
# 0 = no, 1 = yes
  slave: 1
  address: 48
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruChangeoverType
# 0 = Temperature, 1 = Date, 2 = External input
  slave: 1
  address: 51
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSupplyTempOffset
# -10 - 10 °K
  slave: 1
  address: 52
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruWinterStartTemp
# -40 - 40 °C
  slave: 1
  address: 53
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruSummerStartTemp
# -40 - 40 °C
  slave: 1
  address: 54
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruTimeConstant
# 0 - 1000 h
  slave: 1
  address: 55
  input_type: holding
  unit_of_measurement: 'h'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruWinterStartDate
# 1102 = 2 Nov, 930 = 30 Sep
  slave: 1
  address: 56
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruSummerStartDate
# 1102 = 2 Nov, 930 = 30 Sep
  slave: 1
  address: 57
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruFlowDirection
# 0 = standard, 1 = opposite
  slave: 1
  address: 60
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruDamperOpeningTime
# 30-120 sec
  slave: 1
  address: 61
  input_type: holding
  unit_of_measurement: 'sec'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruPreheaterType
# 0 = None, 1 = Electric
  slave: 1
  address: 62
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruPreheaterTempSetpoint
# -40 - 40 °C
  slave: 1
  address: 64
  input_type: holding
  unit_of_measurement: '°C'
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruHeaterType
# 0 = None, 1 = Water, 2 = Electric
  slave: 1
  address: 65
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: TPHeruCoolerType
# 0 = None, 1 = Water
  slave: 1
  address: 67
  input_type: holding
#  unit_of_measurement:
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruT1CalibrationOutsideTemp
# -50 - 50 (-5,0 - 5,0 °K)
  slave: 1
  address: 80
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruT2CalibrationHeatRecoveryTemp
# -50 - 50 (-5,0 - 5,0 °K)
  slave: 1
  address: 81
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruT3CalibrationExtractAirTemp
# -50 - 50 (-5,0 - 5,0 °K)
  slave: 1
  address: 82
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruT4CalibrationExhaustAirTemp
# -50 - 50 (-5,0 - 5,0 °K)
  slave: 1
  address: 83
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruT5CalibrationWaterTemp
# -50 - 50 (-5,0 - 5,0 °K)
  slave: 1
  address: 84
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruT6CalibrationSupplayAirTemp
# -50 - 50 (-5,0 - 5,0 °K)
  slave: 1
  address: 85
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruT7CalibrationRoomTemp
# -50 - 50 (-5,0 - 5,0 °K)
  slave: 1
  address: 86
  input_type: holding
  unit_of_measurement: '°K'
  count: 1
  scale: 0.1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 15

- name: HeruDateTimeYear
  slave: 1
  address: 399
  input_type: holding
#  unit_of_measurement: ''
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 60

- name: HeruDateTimeMonth
# 1 - 12
  slave: 1
  address: 400
  input_type: holding
#  unit_of_measurement: ''
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 60

- name: HeruDateTimeDay
# 1 - 31
  slave: 1
  address: 401
  input_type: holding
#  unit_of_measurement: ''
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 60

- name: HeruDateTimeHours
# 0 - 23
  slave: 1
  address: 402
  input_type: holding
#  unit_of_measurement: ''
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 60

- name: HeruDateTimeMinutes
# 0 - 59
  slave: 1
  address: 403
  input_type: holding
#  unit_of_measurement: ''
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 60

- name: HeruDateTimeSeconds
# 0 - 59
  slave: 1
  address: 404
  input_type: holding
#  unit_of_measurement: ''
  count: 1
  scale: 1
  offset: 0
  precision: 0
  data_type: int16
  scan_interval: 60

.
.
.
heru_switches.yaml

- name: HeruOnOff
  slave: 1
  address: 0
  write_type: coil
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:

- name: HeruOverpressureMode
  slave: 1
  address: 1
  write_type: coil
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:

- name: HeruBoostMode
  slave: 1
  address: 2
  write_type: coil
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:

- name: HeruAwayMode
  slave: 1
  address: 3
  write_type: coil
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:

- name: HeruClearAlarms
  slave: 1
  address: 4
  write_type: coil
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:

- name: HeruResetFilterTimer
  slave: 1
  address: 5
  write_type: coil
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:

- name: HeruSNCenabled
  slave: 1
  address: 18
  write_type: holding
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:
    input_type: holding
    address: 18
    state_on: 1
    state_off: 0 

- name: HeruStandbyTempEvaluationEnabled
  slave: 1
  address: 22
  write_type: holding
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:
    input_type: holding
    address: 22
    state_on: 1
    state_off: 0 

- name: HeruEcoSetpointEnabled
  slave: 1
  address: 48
  write_type: holding
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:
    input_type: holding
    address: 48
    state_on: 1
    state_off: 0 

- name: HeruPreheaterEnabled
  slave: 1
  address: 62
  write_type: holding
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:
    input_type: holding
    address: 62
    state_on: 1
    state_off: 0 

- name: HeruHeaterEnabled
  slave: 1
  address: 66
  write_type: holding
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:
    input_type: holding
    address: 66
    state_on: 1
    state_off: 0 

- name: HeruCoolerEnabled
  slave: 1
  address: 68
  write_type: holding
  command_on: 1
  command_off: 0
  scan_interval: 15
  verify:
    input_type: holding
    address: 68
    state_on: 1
    state_off: 0 

.
.
.
ostberg_heru.yaml

timer:
  heruboostduration:
  heruoverpressureduration:

input_boolean:
  ftx_needs_driven:
    name: "FTX-aggregat behovsstyrd"
    icon: mdi:hvac
  ftx_automatic_afterheater:
    name: "FTX-aggregat automatisk eftervÀrmare"
    icon: mdi:flash

input_number:
  heru_temp_setpoint_economy:
    name: "FTX temp (ekonomilÀge)"
    min: 15
    max: 39
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_temp_setpoint:
    name: "FTX temp (komfortlÀge)"
    min: 15
    max: 40
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_supply_fan_speed:
    name: "Hastighet tilluftsflÀkt"
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:fan
  heru_exhaust_fan_speed:
    name: "Hastighet frÄnluftsflÀkt"
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:fan
  heru_min_supply_fan_speed:
    name: "Minsta hastighet tilluftsflÀkt"
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:fan
  heru_max_supply_fan_speed:
    name: "Högsta hastighet tilluftsflÀkt"
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:fan
  heru_min_supply_temp:
    name: "Minsta temp tilluft"
    min: 15
    max: 19
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:fan
  heru_max_supply_temp:
    name: "Högsta temp tilluft"
    min: 20
    max: 40
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_supply_cold_limit_a:
    name: "KöldgrÀns A tilluft"
    min: 2
    max: 10
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_supply_cold_limit_b:
    name: "KöldgrÀns B tilluft"
    min: 5
    max: 12
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_freeze_protection_limit_temp:
    name: "FrysskyddsgrÀns temp"
    min: 5
    max: 10
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_snc_indoor_outdoor_diff_limit:
    name: "In/ut-diff"
    min: 1
    max: 10
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-celsius
  heru_snc_exhaust_high_limit:
    name: "FrÄnluftstemp hög"
    min: 18
    max: 24
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_snc_exhaust_low_limit:
    name: "FrÄnluftstemp lÄg"
    min: 19
    max: 26
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_snc_standby_temp_eval_interval:
    name: "TemperaturutvÀrderingsintervall i vilolÀge"
    min: 1
    max: 4
    step: 1
    mode: slider
    unit_of_measurement: 'h'
    icon: mdi:timer-sand
  heru_snc_standby_eval_time:
    name: "UtvÀrderingstid"
    min: 5
    max: 15
    step: 1
    mode: slider
    unit_of_measurement: 'min'
    icon: mdi:timer-sand
  heru_snc_min_operating_time:
    name: "Minsta dritftid"
    min: 30
    max: 120
    step: 1
    mode: slider
    unit_of_measurement: 'min'
    icon: mdi:timer-sand
  heru_boost_duration:
    name: "Forceringstid"
    min: 10
    max: 240
    step: 1
    mode: slider
    unit_of_measurement: 'min'
    icon: mdi:timer-sand
  heru_overpressure_duration:
    name: "Övertryckstid"
    min: 10
    max: 60
    step: 1
    mode: slider
    unit_of_measurement: 'min'
    icon: mdi:timer-sand
  heru_winter_start_temp:
    name: "Vinter starttemp"
    min: -40
    max: 40
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_summer_start_temp:
    name: "Sommar starttemp"
    min: -40
    max: 40
    step: 1
    mode: slider
    unit_of_measurement: '°C'
    icon: mdi:temperature-celsius
  heru_t1_calibration_outside_temp:
    name: "T1 kalibrering (utetemp)"
    min: -5
    max: 5
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-kelvin
  heru_t2_calibration_recovery_temp:
    name: "T2 kalibrering (rotor)"
    min: -5
    max: 5
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-kelvin
  heru_t3_calibration_extract_air_temp:
    name: "T3 kalibrering (frÄnluft)"
    min: -5
    max: 5
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-kelvin
  heru_t4_calibration_exhaust_air_temp:
    name: "T4 kalibrering (avluft)"
    min: -5
    max: 5
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-kelvin
  heru_t5_calibration_water_temp:
    name: "T5 kalibrering (vattentemp)"
    min: -5
    max: 5
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-kelvin
  heru_t6_calibration_aupplay_air_temp:
    name: "T6 kalibrering (tilluft)"
    min: -5
    max: 5
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-kelvin
  heru_t7_calibration_room_temp:
    name: "T7 kalibrering (rumstemp)"
    min: -5
    max: 5
    step: 0.1
    mode: slider
    unit_of_measurement: '°K'
    icon: mdi:temperature-kelvin


input_text:
  heru_winter_start_date:
    name: "Vinter startdatum (dag/mÄnad)"
    pattern: "^([1-9]|[12][0-9]|3[01])(\/)([13578]|10|12)$|^([1-9]|[12][0-9]|30)(\/)([469]|11)$|^([1-9]|[12][0-9])(\/2)$"
    icon: mdi:calendar

  heru_summer_start_date:
    name: "Sommar startdatum (dag/mÄnad)"
    pattern: "^([1-9]|[12][0-9]|3[01])(\/)([13578]|10|12)$|^([1-9]|[12][0-9]|30)(\/)([469]|11)$|^([1-9]|[12][0-9])(\/2)$"
    icon: mdi:calendar


input_select:
  heru_regulation_mode:
    name: "RegleringslÀge"
    options:
      - 'tilluft'
      - 'frÄnluft'
      - 'rum'
      - 'frÄnluft s/v'
      - 'rum s/v'
    icon: mdi:tune

  heru_changeover_type:
    name: "VĂ€xlingsmetod s/v"
    options:
      - 'temperatur'
      - 'datum'
      - 'extern ingÄng'
    icon: mdi:tune

input_datetime:
  heru_date_and_time:
    name: "Heru datum och tid"
    has_date: true
    has_time: true

input_button:
  heru_set_date_and_time:
    name: "StÀll in datum och tid"
    icon: mdi:clipboard-text-clock-outline


sensor:
  - platform: template
    sensors:
      heru_supply_air_temp_corrected:
        friendly_name: "Heru rÀttad tilluftstemp"
        value_template: "{{ ((states('sensor.herusupplyairtemp') | float) - (states('sensor.herut6calibrationsupplayairtemp') | float)) | round(0) }}"
        device_class: temperature
        unit_of_measurement: '°C'
      
      needs_driven_exhaust_fan_speed:
        friendly_name: "Behovsstyrd flÀkthastighet frÄnluft"
        value_template: >
          {% set exhfan = 31 %}
          {% if states('group.device_tracker_erik') == 'home' %}
            {% set exhfan = exhfan +8.501 %}
          {%- endif %}
          {% if states('group.device_tracker_jennie') == 'home' %}
            {% set exhfan = exhfan +8.501 %}
          {%- endif %}
          {% if states('group.device_tracker_alvin') == 'home' %}
            {% set exhfan = exhfan +8.501 %}
          {%- endif %}
          {% if states('group.device_tracker_mira') == 'home' %}
            {% set exhfan = exhfan +8.501 %}
          {%- endif %}
          {{ exhfan |round(0) }}

      needs_driven_supply_fan_speed:
        friendly_name: "Behovsstyrd flÀkthastighet tilluft"
        value_template: >
          {% set supfan = 28 %}
          {% if states('group.device_tracker_erik') == 'home' %}
            {% set supfan = supfan +7.751 %}
          {%- endif %}
          {% if states('group.device_tracker_jennie') == 'home' %}
            {% set supfan = supfan +7.751 %}
          {%- endif %}
          {% if states('group.device_tracker_alvin') == 'home' %}
            {% set supfan = supfan +7.751 %}
          {%- endif %}
          {% if states('group.device_tracker_mira') == 'home' %}
            {% set supfan = supfan +7.751 %}
          {%- endif %}
          {{ supfan |round(0) }}

      herucurrentweektimerprogram:
        friendly_name: "HeruCurrentWeektimerProgram"
        value_template: >-
          {% if states('sensor.tpherucurrentweektimerprogram') == '0' %}
            none
          {% elif states('sensor.tpherucurrentweektimerprogram') == '1' %}
            program 1
          {% elif states('sensor.tpherucurrentweektimerprogram') == '2' %}
            program 2
          {% elif states('sensor.tpherucurrentweektimerprogram') == '3' %}
            program 3
          {% elif states('sensor.tpherucurrentweektimerprogram') == '4' %}
            program 4
          {% elif states('sensor.tpherucurrentweektimerprogram') == '5' %}
            program 5
          {% else %}
            error
          {% endif %}

      herucurrentsupplyfanstep:
        friendly_name: "HeruCurrentSupplyFanStep"
        value_template: >-
          {% if states('sensor.tpherucurrentsupplyfanstep') == '0' %}
            off
          {% elif states('sensor.tpherucurrentsupplyfanstep') == '1' %}
            minimum
          {% elif states('sensor.tpherucurrentsupplyfanstep') == '2' %}
            standard
          {% elif states('sensor.tpherucurrentsupplyfanstep') == '3' %}
            maximum
          {% else %}
            none
          {% endif %}

      herucurrentexhaustfanstep:
        friendly_name: "HeruCurrentExhaustFanStep"
        value_template: >-
          {% if states('sensor.tpherucurrentexhaustfanstep') == '0' %}
            off
          {% elif states('sensor.tpherucurrentexhaustfanstep') == '1' %}
            minimum
          {% elif states('sensor.tpherucurrentexhaustfanstep') == '2' %}
            standard
          {% elif states('sensor.tpherucurrentexhaustfanstep') == '3' %}
            maximum
          {% else %}
            none
          {% endif %}

      heruregulationmode:
        friendly_name: "HeruRegulationMode"
        value_template: >-
          {% if states('sensor.tpheruregulationmode') == '0' %}
            supply
          {% elif states('sensor.tpheruregulationmode') == '1' %}
            extract
          {% elif states('sensor.tpheruregulationmode') == '2' %}
            room
          {% elif states('sensor.tpheruregulationmode') == '3' %}
            extract s/w
          {% elif states('sensor.tpheruregulationmode') == '4' %}
            room s/w
          {% else %}
            none
          {% endif %}

      herufiltermeasurementweekday:
        friendly_name: "HeruFilterMeasurementWeekday"
        value_template: >-
          {% if states('sensor.tpherufiltermeasurementweekday') == '0' %}
            monday
          {% elif states('sensor.tpherufiltermeasurementweekday') == '1' %}
            tuesday
          {% elif states('sensor.tpherufiltermeasurementweekday') == '2' %}
            wednesday
          {% elif states('sensor.tpherufiltermeasurementweekday') == '3' %}
            thursday
          {% elif states('sensor.tpherufiltermeasurementweekday') == '4' %}
            friday
          {% elif states('sensor.tpherufiltermeasurementweekday') == '5' %}
            saturday
          {% elif states('sensor.tpherufiltermeasurementweekday') == '6' %}
            sunday
          {% else %}
            none
          {% endif %}

      herusncenabled:
        friendly_name: "HeruSNCenabled"
        value_template: >-
          {% if states('sensor.tpherusncenabled') == '0' %}
            no
          {% elif states('sensor.tpherusncenabled') == '1' %}
            yes
          {% else %}
            none
          {% endif %}

      herustandbytempevaluationenabled:
        friendly_name: "HeruStandbyTempEvaluationEnabled"
        value_template: >-
          {% if states('sensor.tpherustandbytempevaluationenabled') == '0' %}
            no
          {% elif states('sensor.tpherustandbytempevaluationenabled') == '1' %}
            yes
          {% else %}
            none
          {% endif %}

      heruecosetpointenabled:
        friendly_name: "HeruEcoSetpointEnabled"
        value_template: >-
          {% if states('sensor.tpheruecosetpointenabled') == '0' %}
            no
          {% elif states('sensor.tpheruecosetpointenabled') == '1' %}
            yes
          {% else %}
            none
          {% endif %}

      heruqualitysensor1_type:
        friendly_name: "HeruQualitySensor1_type"
        value_template: >-
          {% if states('sensor.tpheruqualitysensor1_type') == '0' %}
            none
          {% elif states('sensor.tpheruqualitysensor1_type') == '1' %}
            RH
          {% elif states('sensor.tpheruqualitysensor1_type') == '2' %}
            CO2
          {% elif states('sensor.tpheruqualitysensor1_type') == '3' %}
            VOC
          {% else %}
            error
          {% endif %}

      heruqualitysensor2_type:
        friendly_name: "HeruQualitySensor2_type"
        value_template: >-
          {% if states('sensor.tpheruqualitysensor2_type') == '0' %}
            none
          {% elif states('sensor.tpheruqualitysensor2_type') == '1' %}
            RH
          {% elif states('sensor.tpheruqualitysensor2_type') == '2' %}
            CO2
          {% elif states('sensor.tpheruqualitysensor2_type') == '3' %}
            VOC
          {% else %}
            error
          {% endif %}

      heruqualitysensor3_type:
        friendly_name: "HeruQualitySensor3_type"
        value_template: >-
          {% if states('sensor.tpheruqualitysensor3_type') == '0' %}
            none
          {% elif states('sensor.tpheruqualitysensor3_type') == '1' %}
            RH
          {% elif states('sensor.tpheruqualitysensor3_type') == '2' %}
            CO2
          {% elif states('sensor.tpheruqualitysensor3_type') == '3' %}
            VOC
          {% else %}
            error
          {% endif %}

      herufiremode:
        friendly_name: "HeruFireMode"
        value_template: >-
          {% if states('sensor.tpherufiremode') == '0' %}
            fans off
          {% elif states('sensor.tpherufiremode') == '1' %}
            exhaust fan only
          {% elif states('sensor.tpherufiremode') == '2' %}
            supply fan only
          {% elif states('sensor.tpherufiremode') == '3' %}
            both fans
          {% else %}
            none
          {% endif %}

      herusupplypressuresensortype:
        friendly_name: "HeruSupplyPressureSensorType"
        value_template: >-
          {% if states('sensor.tpherusupplypressuresensortype') == '0' %}
            none
          {% elif states('sensor.tpherusupplypressuresensortype') == '1' %}
            0..100 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '2' %}
            0..200 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '3' %}
            0..300 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '4' %}
            0..500 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '5' %}
            0..700 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '6' %}
            0..1000 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '7' %}
            0..1250 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '8' %}
            0..1500 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '9' %}
            0..2000 Pa
          {% elif states('sensor.tpherusupplypressuresensortype') == '10' %}
            0..2500 Pa
          {% else %}
            error
          {% endif %}

      heruexhaustpressuresensortype:
        friendly_name: "HeruExhaustPressureSensorType"
        value_template: >-
          {% if states('sensor.tpheruexhaustpressuresensortype') == '0' %}
            none
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '1' %}
            0..100 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '2' %}
            0..200 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '3' %}
            0..300 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '4' %}
            0..500 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '5' %}
            0..700 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '6' %}
            0..1000 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '7' %}
            0..1250 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '8' %}
            0..1500 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '9' %}
            0..2000 Pa
          {% elif states('sensor.tpheruexhaustpressuresensortype') == '10' %}
            0..2500 Pa
          {% else %}
            error
          {% endif %}

      herufiltermeasurementmode:
        friendly_name: "HeruFilterMeasurementMode"
        value_template: >-
          {% if states('sensor.tpherufiltermeasurementmode') == '0' %}
            off
          {% elif states('sensor.tpherufiltermeasurementmode') == '1' %}
            switch
          {% elif states('sensor.tpherufiltermeasurementmode') == '2' %}
            speed inc.
          {% elif states('sensor.tpherufiltermeasurementmode') == '3' %}
            differential
          {% else %}
            none
          {% endif %}

      heruchangeovertype:
        friendly_name: "HeruChangeoverType"
        value_template: >-
          {% if states('sensor.tpheruchangeovertype') == '0' %}
            temperature
          {% elif states('sensor.tpheruchangeovertype') == '1' %}
            date
          {% elif states('sensor.tpheruchangeovertype') == '2' %}
            external input
          {% else %}
            none
          {% endif %}

      heruheatertype:
        friendly_name: "HeruHeaterType"
        value_template: >-
          {% if states('sensor.tpheruheatertype') == '0' %}
            none
          {% elif states('sensor.tpheruheatertype') == '1' %}
            water
          {% elif states('sensor.tpheruheatertype') == '2' %}
            electric
          {% else %}
            error
          {% endif %}

      heruflowdirection:
        friendly_name: "HeruFlowDirection"
        value_template: >-
          {% if states('sensor.tpheruflowdirection') == '0' %}
            standard
          {% elif states('sensor.tpheruflowdirection') == '1' %}
            opposite
          {% else %}
            none
          {% endif %}

      herupreheatertype:
        friendly_name: "HeruPreheaterType"
        value_template: >-
          {% if states('sensor.tpherupreheatertype') == '0' %}
            none
          {% elif states('sensor.tpherupreheatertype') == '1' %}
            electric
          {% else %}
            error
          {% endif %}

      herucoolertype:
        friendly_name: "HeruCoolerType"
        value_template: >-
          {% if states('sensor.tpherucoolertype') == '0' %}
            none
          {% elif states('sensor.tpherucoolertype') == '1' %}
            water
          {% else %}
            error
          {% endif %}

      herufiresensortype:
        friendly_name: "HeruFireSensorType"
        value_template: >-
          {% if states('sensor.tpherufiresensortype') == '0' %}
            none
          {% elif states('sensor.tpherufiresensortype') == '1' %}
            normally open (NO)
          {% elif states('sensor.tpherufiresensortype') == '2' %}
            normally closed (NC)
          {% else %}
            error
          {% endif %}
      herusensoropenalarmclass:
        friendly_name: "HeruSensorOpenAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(2) > 0 %} B {% else %} A {% endif %}

      herusensorshortedalarmclass:
        friendly_name: "HeruSensorShortedAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(4) > 0 %} B {% else %} A {% endif %}

      heruoverheatprotectionlarmclass:
        friendly_name: "HeruOverheatProtectionAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(8) > 0 %} B {% else %} A {% endif %}

      herufreezealarmclass:
        friendly_name: "HeruFreezeAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(16) > 0 %} B {% else %} A {% endif %}

      herusupplytemperaturelowalarmclass:
        friendly_name: "HeruSupplyTemperatureLowAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(32) > 0 %} B {% else %} A {% endif %}

      herurotortemperaturelowalarmclass:
        friendly_name: "HeruRotorTemperatureLowAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(64) > 0 %} B {% else %} A {% endif %}

      herufanfailurealarmclass:
        friendly_name: "HeruFanFailureAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(128) > 0 %} B {% else %} A {% endif %}

      heruheatexchangeralarmclass:
        friendly_name: "HeruHeatExchangerAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(256) > 0 %} B {% else %} A {% endif %}

      heruductpressuredeviationalarmclass:
        friendly_name: "HeruDuctPressureDeviationAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(512) > 0 %} B {% else %} A {% endif %}

      herupumpalarmclass:
        friendly_name: "HeruPumpAlarmClass"
        value_template: >-
          {% if states('sensor.tpherualarmclasses')|int(default=0)|bitwise_and(1024) > 0 %} B {% else %} A {% endif %}

      heruaalarmrelaycontactfunction:
        friendly_name: "HeruAalarmRelayContactFunction"
        value_template: >-
          {% if states('sensor.tpherualarmrelaycontactfunction')|int(default=0)|bitwise_and(1) > 0 %} NC {% else %} NO {% endif %}

      herubalarmrelaycontactfunction:
        friendly_name: "HeruBalarmRelayContactFunction"
        value_template: >-
          {% if states('sensor.tpherualarmrelaycontactfunction')|int(default=0)|bitwise_and(2) > 0 %} NC {% else %} NO {% endif %}

      herurunrelaycontactfunction:
        friendly_name: "HeruRunRelayContactFunction"
        value_template: >-
          {% if states('sensor.tpherualarmrelaycontactfunction')|int(default=0)|bitwise_and(4) > 0 %} NC {% else %} NO {% endif %}

      heruwinterstartdate:
        friendly_name: "HeruWinterStartDate"
        value_template: >-
          {% set startdate = '%0.4d' % states('sensor.tpheruwinterstartdate') | int %}
          {% set month = startdate | regex_findall_index(find='[0-9]{2}', index=0, ignorecase=false) | int %}
          {% set day = startdate | regex_findall_index(find='[0-9]{2}', index=1, ignorecase=false) | int %}
          {{ day }}/{{ month }}

      herusummerstartdate:
        friendly_name: "HeruSummerStartDate"
        value_template: >-
          {% set startdate = '%0.4d' % states('sensor.tpherusummerstartdate') | int %}
          {% set month = startdate | regex_findall_index(find='[0-9]{2}', index=0, ignorecase=false) | int %}
          {% set day = startdate | regex_findall_index(find='[0-9]{2}', index=1, ignorecase=false) | int %}
          {{ day }}/{{ month }}

      herudatetime:
        friendly_name: "HeruDateTime"
        value_template: >-
          {% set year = states('sensor.herudatetimeyear') | int %}
          {% set month = '%0.2d' % states('sensor.herudatetimemonth') | int %}
          {% set day = '%0.2d' % states('sensor.herudatetimeday') | int %}
          {% set hours = '%0.2d' % states('sensor.herudatetimehours') | int %}
          {% set minutes = '%0.2d' % states('sensor.herudatetimeminutes') | int %}
          {% set seconds = '%0.2d' % states('sensor.herudatetimeseconds') | int %}
          {{ year~'-'~month~'-'~day~' '~hours~':'~minutes~':00' }}


binary_sensor:
  - platform: template
    sensors:
      herusensort1open:
        friendly_name: "HeruSensorT1open"
        value_template: "{{ states('sensor.tpherusensorsopen')|int(default=0)|bitwise_and(1) > 0 }}"

      herusensort2open:
        friendly_name: "HeruSensorT2open"
        value_template: "{{ states('sensor.tpherusensorsopen')|int(default=0)|bitwise_and(2) > 0 }}"

      herusensort3open:
        friendly_name: "HeruSensorT3open"
        value_template: "{{ states('sensor.tpherusensorsopen')|int(default=0)|bitwise_and(4) > 0 }}"

      herusensort4open:
        friendly_name: "HeruSensorT4open"
        value_template: "{{ states('sensor.tpherusensorsopen')|int(default=0)|bitwise_and(8) > 0 }}"

      herusensort5open:
        friendly_name: "HeruSensorT5open"
        value_template: "{{ states('sensor.tpherusensorsopen')|int(default=0)|bitwise_and(16) > 0 }}"

      herusensort6open:
        friendly_name: "HeruSensorT6open"
        value_template: "{{ states('sensor.tpherusensorsopen')|int(default=0)|bitwise_and(32) > 0 }}"

      herusensort1shorted:
        friendly_name: "HeruSensorT1shorted"
        value_template: "{{ states('sensor.tpherusensorsshorted')|int(default=0)|bitwise_and(1) > 0 }}"

      herusensort2shorted:
        friendly_name: "HeruSensorT2shorted"
        value_template: "{{ states('sensor.tpherusensorsshorted')|int(default=0)|bitwise_and(2) > 0 }}"

      herusensort3shorted:
        friendly_name: "HeruSensorT3shorted"
        value_template: "{{ states('sensor.tpherusensorsshorted')|int(default=0)|bitwise_and(4) > 0 }}"

      herusensort4shorted:
        friendly_name: "HeruSensorT4shorted"
        value_template: "{{ states('sensor.tpherusensorsshorted')|int(default=0)|bitwise_and(8) > 0 }}"

      herusensort5shorted:
        friendly_name: "HeruSensorT5shorted"
        value_template: "{{ states('sensor.tpherusensorsshorted')|int(default=0)|bitwise_and(16) > 0 }}"

      herusensort6shorted:
        friendly_name: "HeruSensorT6shorted"
        value_template: "{{ states('sensor.tpherusensorsshorted')|int(default=0)|bitwise_and(32) > 0 }}"



      herufirealarmrelayoutput:
        friendly_name: "HeruFireAlarmRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(1) > 0 }}"

      herusensoropenrelayoutput:
        friendly_name: "HeruOensorOpenRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(2) > 0 }}"

      herusensorshortedrelayoutput:
        friendly_name: "HerusensorShortedRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(4) > 0 }}"

      heruoverheatprotectionrelayoutput:
        friendly_name: "HeruOverheatProtectionRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(8) > 0 }}"

      herufreezealarmrelayoutput:
        friendly_name: "HeruFreezeAlarmRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(16) > 0 }}"

      herusupplytemperaturelowrelayoutput:
        friendly_name: "HeruSupplyTemperatureLowRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(32) > 0 }}"

      herurotortemperaturelowrelayoutput:
        friendly_name: "HeruRotorTemperatureLowRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(64) > 0 }}"

      herufanfailurerelayoutput:
        friendly_name: "HeruFanFailureRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(128) > 0 }}"

      heruheatexchangerrelayoutput:
        friendly_name: "HeruHeatExchangerRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(256) > 0 }}"

      heruductpressuredeviationrelayoutput:
        friendly_name: "HeruDuctPressureDeviationRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(512) > 0 }}"

      herupumpalarmrelayoutput:
        friendly_name: "HeruPumpAlarmRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(1024) > 0 }}"

      herufilterrelayoutput:
        friendly_name: "HeruFilterRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(2048) > 0 }}"

      herufiltertimerrelayoutput:
        friendly_name: "HeruFilterTimerRelayOutput"
        value_template: "{{ states('sensor.tpherualarmrelayoutput')|int(default=0)|bitwise_and(4096) > 0 }}"


switch:
  - platform: template
    switches:
      heruoverpressuremode_template:
        value_template: "{{ states('switch.heruoverpressuremode') == 'on' }}"
        turn_on:
          - service: switch.turn_on
            data:
              entity_id: switch.heruoverpressuremode
          - service: homeassistant.update_entity
            data:
              entity_id: switch.heruoverpressuremode
        turn_off:
          - service: switch.turn_off
            data:
              entity_id: switch.heruoverpressuremode
          - service: homeassistant.update_entity
            data:
              entity_id: switch.heruoverpressuremode
        availability_template: "{% if not states('switch.heruoverpressuremode') == 'unavailable' %}true{% else %}false{% endif %}"
        icon_template: "{% if states('switch.heruoverpressuremode') == 'on' %}mdi:fireplace{% else %}mdi:fireplace-off{% endif %}" 

      heruboostmode_template:
        value_template: "{{ states('switch.heruboostmode') == 'on' }}"
        turn_on:
          - service: switch.turn_on
            data:
              entity_id: switch.heruboostmode
          - service: homeassistant.update_entity
            data:
              entity_id: switch.heruboostmode
        turn_off:
          - service: switch.turn_off
            data:
              entity_id: switch.heruboostmode
          - service: homeassistant.update_entity
            data:
              entity_id: switch.heruboostmode
        availability_template: "{% if not states('switch.heruboostmode') == 'unavailable' %}true{% else %}false{% endif %}"
        icon_template: "{% if states('switch.heruboostmode') == 'on' %}mdi:speedometer{% else %}mdi:speedometer-slow{% endif %}" 

      heruawaymode_template:
        value_template: "{{ states('switch.heruawaymode') == 'on' }}"
        turn_on:
          - service: switch.turn_on
            data:
              entity_id: switch.heruawaymode
          - service: homeassistant.update_entity
            data:
              entity_id: switch.heruawaymode
        turn_off:
          - service: switch.turn_off
            data:
              entity_id: switch.heruawaymode
          - service: homeassistant.update_entity
            data:
              entity_id: switch.heruawaymode
        availability_template: "{% if not states('switch.heruawaymode') == 'unavailable' %}true{% else %}false{% endif %}"
        icon_template: "{% if states('switch.heruawaymode') == 'on' %}mdi:briefcase-clock-outline{% else %}mdi:briefcase-outline{% endif %}" 

      herufirealarmrelayoutput:
        value_template: >
          {% set bit = 1 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 1
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 1
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herusensoropenrelayoutput:
        value_template: >
          {% set bit = 2 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 2
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 2
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herusensorshortedrelayoutput:
        value_template: >
          {% set bit = 3 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 3
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 3
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      heruoverheatprotectionrelayoutput:
        value_template: >
          {% set bit = 4 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 4
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 4
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herufreezealarmrelayoutput:
        value_template: >
          {% set bit = 5 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 5
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 5
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herusupplytemperaturelowrelayoutput:
        value_template: >
          {% set bit = 6 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 6
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 6
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herurotortemperaturelowrelayoutput:
        value_template: >
          {% set bit = 7 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 7
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 7
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herufanfailurerelayoutput:
        value_template: >
          {% set bit = 8 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 8
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 8
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      heruheatexchangerrelayoutput:
        value_template: >
          {% set bit = 9 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 9
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 9
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      heruductpressuredeviationrelayoutput:
        value_template: >
          {% set bit = 10 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 10
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 10
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herupumpalarmrelayoutput:
        value_template: >
          {% set bit = 11 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 11
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 11
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herufilterrelayoutput:
        value_template: >
          {% set bit = 12 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 12
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 12
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput

      herufiltertimerrelayoutput:
        value_template: >
          {% set bit = 13 %}
          {{ states('sensor.tpherualarmrelayoutput') | int(default=0) | bitwise_and(2 ** (bit | int - 1)) > 0 }}
        turn_on:
          - service: script.write_register_turn_on_bit
            data:
              bit: 13
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput
        turn_off:
          - service: script.write_register_turn_off_bit
            data:
              bit: 13
              hub: heru
              unit: 1
              address: 45
              sensor_value: sensor.tpherualarmrelayoutput


automation:
  - id: heru_room_temp
    alias: 'Heru rumstemperatur'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.inomhus_temperature
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 86
          value: "{{ (trigger.to_state.state | float(default=16.7) * 10 - 217) | int }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.heruroomtemp

  - id: heru_auto_adjust_supply_air_temp_offset
    alias: 'Heru autojustering offset tilluftstemp'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herucurrentcoolingpower
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 85
          value: "{{ (trigger.to_state.state | float(default=0.0) * 0.196) | round(0) }}"

  - id: activate_electric_heater_if_supply_air_temp_below_6
    alias: 'Aktivera eleftervÀrmare om tilluft under 6 grader'
    initial_state: 'on'
    trigger:
      - platform: numeric_state
        entity_id: sensor.herusupplyairtemp
        below: 8
    condition:
      - condition: state
        entity_id: input_boolean.ftx_automatic_afterheater
        state: 'on'
    action:
      - service: switch.turn_on
        data:
          entity_id: switch.heruheaterenabled

  - id: deactivate_electric_heater_if_supply_air_temp_above_10
    alias: 'Avaktivera eleftervÀrmare om tilluft över 10 grader'
    initial_state: 'on'
    trigger:
      - platform: numeric_state
        entity_id: sensor.herusupplyairtemp
        above: 12
    condition:
      - condition: state
        entity_id: input_boolean.ftx_automatic_afterheater
        state: 'on'
    action:
      - service: switch.turn_off
        data:
          entity_id: switch.heruheaterenabled

  - id: heru_startup_1st_phase_notify
    alias: 'Notifiering vid Heru uppstartsfas 1'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: binary_sensor.herustartup1stphase
        to: 'on'
    condition: []
    action:
      - service: notify.erik
        data:
          message: 'FTX aggregat - uppstart 1:a fas' 

  - id: heru_startup_2st_phase_notify
    alias: 'Notifiering vid Heru uppstartsfas 2'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: binary_sensor.herustartup2stphase
        to: 'on'
    condition: []
    action:
      - service: notify.erik
        data:
          message: 'FTX aggregat - uppstart 2:a fas' 

  - id: notify_erik_if_heru_alarm_present
    alias: 'Notifiera Erik om Heru larmar'
    initial_state: 'on'
    trigger:
      - platform: event
        event_type: state_changed
    condition:
      - condition: template
        value_template: >
          {{ trigger.event.data.entity_id.startswith('binary_sensor.heru')
             and trigger.event.data.entity_id.endswith('alarm')
             and trigger.event.data.old_state.state != 'unavailable'
             and trigger.event.data.new_state.state != 'unavailable'
             and trigger.event.data.old_state is not none
             and trigger.event.data.new_state is not none }}
    action:
      - service: notify.erik
        data:
          message: "FTX alarm. {{ trigger.event.data.old_state.name }} has changed from {{ trigger.event.data.old_state.state }} to {{ trigger.event.data.new_state.state }}"

  - id: set_heru_supply_fan
    alias: 'StĂ€ll in Östberg Heru tilluftflĂ€kt'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.needs_driven_supply_fan_speed
      - platform: state
        entity_id: input_boolean.ftx_needs_driven
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ftx_needs_driven
        state: 'on'
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 2
          value: "{{ states('sensor.needs_driven_supply_fan_speed') | int(default=59) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentsupplyfanpower
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentsupplyfanspeed

  - id: set_heru_exhaust_fan
    alias: 'StĂ€ll in Östberg Heru frĂ„nluftflĂ€kt'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.needs_driven_exhaust_fan_speed
      - platform: state
        entity_id: input_boolean.ftx_needs_driven
        from: 'off'
        to: 'on'
    condition:
      - condition: state
        entity_id: input_boolean.ftx_needs_driven
        state: 'on'
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 3
          value: "{{ states('sensor.needs_driven_exhaust_fan_speed') | int(default=65) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentexhaustfanpower
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentexhaustfanspeed

  - id: ftx_needs_driven_off
    alias: 'FTX behovsstyrd av'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_boolean.ftx_needs_driven
        from: 'on'
        to: 'off'
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 2
          value: 59 #StandardvÀrde i % för tilluftsflÀkten enligt instÀllning av Anders Hellström pÄ Optimal ventilation 
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 3
          value: 65 #StandardvÀrde i % för frÄnluftsflÀkten enligt instÀllning av Anders Hellström pÄ Optimal ventilation
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentsupplyfanpower
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentsupplyfanspeed
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentexhaustfanpower
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herucurrentexhaustfanspeed

  - id: set_heru_temp_eco
    alias: 'StÀll in FTX temp (ekonomi)'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_temp_setpoint_economy
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 0
          value: "{{ trigger.to_state.state | int(default=15) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herutempsetpointeconomy
  - id: update_heru_temp_slider_eco
    alias: 'Uppdatera slider - FTX temp (ekonomi)'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herutempsetpointeconomy
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_temp_setpoint_economy
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_temp
    alias: 'StÀll in FTX temp'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_temp_setpoint
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 1
          value: "{{ trigger.to_state.state | int(default=23) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herutempsetpoint
  - id: update_heru_temp_slider
    alias: 'Uppdatera slider - FTX temp'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herutempsetpoint
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_temp_setpoint
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_supply_fan_speed
    alias: 'StÀll in FTX flÀkthastighet tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_supply_fan_speed
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 2
          value: "{{ trigger.to_state.state | int(default=59) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusupplyfanspeed
  - id: update_heru_supply_fan_speed_slider
    alias: 'Uppdatera slider - FTX flÀkthastighet tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusupplyfanspeed
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_supply_fan_speed
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_exhaust_fan_speed
    alias: 'StÀll in FTX flÀkthastighet frÄnluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_exhaust_fan_speed
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 3
          value: "{{ trigger.to_state.state | int(default=65) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.heruexhaustfanspeed
  - id: update_heru_exhaust_fan_speed_slider
    alias: 'Uppdatera slider - FTX flÀkthastighet frÄnluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.heruexhaustfanspeed
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_exhaust_fan_speed
          value: "{{ trigger.to_state.state }}"
  - id: set_heru_min_supply_fan_speed
    alias: 'StÀll in FTX minsta flÀkthastighet tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_min_supply_fan_speed
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 4
          value: "{{ trigger.to_state.state | int(default=30) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.heruminsupplyfanspeed
  - id: update_heru_min_supply_fan_speed_slider
    alias: 'Uppdatera slider - FTX mista flÀkthastighet tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.heruminsupplyfanspeed
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_min_supply_fan_speed
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_max_supply_fan_speed
    alias: 'StÀll in FTX högsta flÀkthastighet tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_max_supply_fan_speed
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 5
          value: "{{ trigger.to_state.state | int(default=97) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herumaxsupplyfanspeed
  - id: update_heru_max_supply_fan_speed_slider
    alias: 'Uppdatera slider - FTX högsta flÀkthastighet tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herumaxsupplyfanspeed
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_max_supply_fan_speed
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_min_supply_temp
    alias: 'StÀll in FTX minsta temperatur tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_min_supply_temp
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 12
          value: "{{ trigger.to_state.state | int(default=15) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.heruminsupplytemp
  - id: update_heru_min_supply_temp_slider
    alias: 'Uppdatera slider - FTX minsta temperatur tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.heruminsupplytemp
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_min_supply_temp
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_max_supply_temp
    alias: 'StÀll in FTX högsta temperatur tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_max_supply_temp
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 13
          value: "{{ trigger.to_state.state | int(default=25) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herumaxsupplytemp
  - id: update_heru_max_supply_temp_slider
    alias: 'Uppdatera slider - FTX högsta temperatur tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herumaxsupplytemp
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_max_supply_temp
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_supply_cold_limit_a
    alias: 'StÀll in FTX köldgrÀns A tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_supply_cold_limit_a
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 14
          value: "{{ trigger.to_state.state | int(default=2) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusupplycoldlimita
  - id: update_heru_supply_cold_limit_a_slider
    alias: 'Uppdatera slider - FTX köldgrÀns A tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusupplycoldlimita
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_supply_cold_limit_a
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_supply_cold_limit_b
    alias: 'StÀll in FTX köldgrÀns B tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_supply_cold_limit_b
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 15
          value: "{{ trigger.to_state.state | int(default=5) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusupplycoldlimitb
  - id: update_heru_supply_cold_limit_b_slider
    alias: 'Uppdatera slider - FTX köldgrÀns B tilluft'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusupplycoldlimitb
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_supply_cold_limit_b
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_freeze_protection_limit_temp
    alias: 'StÀll in FTX frysskyddsgrÀns temp'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_freeze_protection_limit_temp
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 16
          value: "{{ trigger.to_state.state | int(default=6) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herufreezeprotectionlimittemp
  - id: update_heru_freeze_protection_limit_temp_slider
    alias: 'Uppdatera slider - FTX frysskyddsgrÀns temp'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herufreezeprotectionlimittemp
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_freeze_protection_limit_temp
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_snc_indoor_outdoor_diff_limit
    alias: 'StÀll in FTX nattkyla in/ut-diff'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_snc_indoor_outdoor_diff_limit
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 19
          value: "{{ trigger.to_state.state | float(default=5.0) * 10 }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusncindooroutdoordifflimit
  - id: update_heru_snc_indoor_outdoor_diff_limit_slider
    alias: 'Uppdatera slider - FTX nattkyla in/ut-diff'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusncindooroutdoordifflimit
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_snc_indoor_outdoor_diff_limit
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_snc_exhaust_high_limit
    alias: 'StÀll in FTX nattkyla FrÄnluftstemp hög'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_snc_exhaust_high_limit
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 20
          value: "{{ trigger.to_state.state | int(default=23) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusncexhausthighlimit
  - id: update_heru_snc_exhaust_high_limit_slider
    alias: 'Uppdatera slider - FTX nattkyla FrÄnluftstemp hög'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusncexhausthighlimit
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_snc_exhaust_high_limit
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_snc_exhaust_low_limit
    alias: 'StÀll in FTX nattkyla FrÄnluftstemp lÄg'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_snc_exhaust_low_limit
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 21
          value: "{{ trigger.to_state.state | int(default=21) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusncexhaustlowlimit
  - id: update_heru_snc_exhaust_low_limit_slider
    alias: 'Uppdatera slider - FTX nattkyla FrÄnluftstemp lÄg'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusncexhaustlowlimit
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_snc_exhaust_low_limit
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_snc_standby_temp_eval_interval
    alias: 'StÀll in FTX temperaturutvÀrderingsintervall i vilolÀge'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_snc_standby_temp_eval_interval
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 23
          value: "{{ trigger.to_state.state | int(default=4) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusncstandbytempevalinterval
  - id: update_heru_snc_standby_temp_eval_interval_slider
    alias: 'Uppdatera slider - FTX temperaturutvÀrderingsintervall i vilolÀge'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusncstandbytempevalinterval
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_snc_standby_temp_eval_interval
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_snc_standby_eval_time
    alias: 'StÀll in FTX utvÀrderingstid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_snc_standby_eval_time
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 24
          value: "{{ trigger.to_state.state | int(default=5) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusncstandbyevaltime
  - id: update_heru_snc_standby_eval_time_slider
    alias: 'Uppdatera slider - FTX utvÀrderingstid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusncstandbyevaltime
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_snc_standby_eval_time
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_snc_min_operating_time
    alias: 'StÀll in FTX minsta drifttid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_snc_min_operating_time
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 25
          value: "{{ trigger.to_state.state | int(default=30) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusncminoperatingtime
  - id: update_heru_snc_min_operating_time_slider
    alias: 'Uppdatera slider - FTX minsta drifttid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusncminoperatingtime
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_snc_min_operating_time
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_boost_duration
    alias: 'StÀll in FTX forceringstid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_boost_duration
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 26
          value: "{{ trigger.to_state.state | int(default=180) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.heruboostduration
  - id: update_heru_boost_duration_slider
    alias: 'Uppdatera slider - FTX forceringstid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.heruboostduration
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_boost_duration
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_overpressure_duration
    alias: 'StÀll in FTX övertryckstid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_overpressure_duration
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 27
          value: "{{ trigger.to_state.state | int(default=15) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.heruoverpressureduration
  - id: update_heru_overpressure_duration_slider
    alias: 'Uppdatera slider - FTX övertryckstid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.heruoverpressureduration
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_overpressure_duration
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_winter_start_temp
    alias: 'StÀll in FTX vinter starttemperatur'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_winter_start_temp
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 53
          value: "{{ trigger.to_state.state | int(default=5) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.heruwinterstarttemp
  - id: update_heru_winter_start_temp_slider
    alias: 'Uppdatera slider - FTX vinter starttemperatur'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.heruwinterstarttemp
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_winter_start_temp
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_summer_start_temp
    alias: 'StÀll in FTX sommar starttemperatur'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: input_number.heru_summer_start_temp
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 54
          value: "{{ trigger.to_state.state | int(default=15) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.herusummerstarttemp
  - id: update_heru_summer_start_temp_slider
    alias: 'Uppdatera slider - FTX sommar starttemperatur'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusummerstarttemp
    condition: []
    action:
      - service: input_number.set_value
        data:
          entity_id: input_number.heru_summer_start_temp
          value: "{{ trigger.to_state.state }}"

  - id: set_heru_date_and_time
    alias: 'StÀll in FTX datum och tid'
    initial_state: 'on'
    mode: single
    max_exceeded: silent
    trigger:
      - platform: state
        entity_id: input_button.heru_set_date_and_time
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 399
          value: "{{ state_attr('input_datetime.heru_date_and_time','year') }}"
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 400
          value: "{{ state_attr('input_datetime.heru_date_and_time','month') }}"
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 401
          value: "{{ state_attr('input_datetime.heru_date_and_time','day') }}"
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 402
          value: "{{ state_attr('input_datetime.heru_date_and_time','hour') }}"
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 403
          value: "{{ state_attr('input_datetime.heru_date_and_time','minute') }}"
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 404
          value: "{{ state_attr('input_datetime.heru_date_and_time','second') }}"
  - id: update_heru_date_and_time
    alias: 'Uppdatera FTX datum och tid'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herudatetime
    condition: []
    action:
      - service: input_datetime.set_datetime
        target:
          entity_id: input_datetime.heru_date_and_time
        data:
          datetime: "{{ trigger.to_state.state }}"


  - id: update_heru_helpers_at_system_start
    alias: 'Uppdatera Heru-hjÀlpare vid systemstart'
    initial_state: 'on'
    trigger:
      - platform: homeassistant
        event: start
    condition: []
    action:
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_boost_duration
        data:
          value: "{{ states.sensor.heruboostduration.state | int(default=180) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_freeze_protection_limit_temp
        data:
          value: "{{ states.sensor.herufreezeprotectionlimittemp.state | int(default=6) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_snc_exhaust_high_limit
        data:
          value: "{{ states.sensor.herusncexhausthighlimit.state | int(default=23) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_snc_exhaust_low_limit
        data:
          value: "{{ states.sensor.herusncexhaustlowlimit.state | int(default=21) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_temp_setpoint_economy
        data:
          value: "{{ states.sensor.herutempsetpointeconomy.state | int(default=15) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_temp_setpoint
        data:
          value: "{{ states.sensor.herutempsetpoint.state | int(default=23) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_exhaust_fan_speed
        data:
          value: "{{ states.sensor.heruexhaustfanspeed.state | int(default=65) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_supply_fan_speed
        data:
          value: "{{ states.sensor.herusupplyfanspeed.state | int(default=59) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_max_supply_fan_speed
        data:
          value: "{{ states.sensor.herumaxsupplyfanspeed.state | int(default=97) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_max_supply_temp
        data:
          value: "{{ states.sensor.herumaxsupplytemp.state | int(default=25) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_snc_indoor_outdoor_diff_limit
        data:
          value: "{{ states.sensor.herusncindooroutdoordifflimit.state | int(default=50) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_supply_cold_limit_a
        data:
          value: "{{ states.sensor.herusupplycoldlimita.state | int(default=2) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_supply_cold_limit_b
        data:
          value: "{{ states.sensor.herusupplycoldlimitb.state | int(default=5) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_snc_min_operating_time
        data:
          value: "{{ states.sensor.herusncminoperatingtime.state | int(default=30) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_min_supply_fan_speed
        data:
          value: "{{ states.sensor.heruminsupplyfanspeed.state | int(default=30) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_min_supply_temp
        data:
          value: "{{ states.sensor.heruminsupplytemp.state | int(default=15) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_snc_standby_temp_eval_interval
        data:
          value: "{{ states.sensor.herusncstandbytempevalinterval.state | int(default=4) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_snc_standby_eval_time
        data:
          value: "{{ states.sensor.herusncstandbyevaltime.state | int(default=5) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_overpressure_duration
        data:
          value: "{{ states.sensor.heruoverpressureduration.state | int(default=15) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_winter_start_temp
        data:
          value: "{{ states.sensor.heruwinterstarttemp.state | int(default=5) }}"
      - service: input_number.set_value
        target:
          entity_id: input_number.heru_summer_start_temp
        data:
          value: "{{ states.sensor.herusummerstarttemp.state | int(default=15) }}"


      - service: input_text.set_value
        target:
          entity_id: input_text.heru_winter_start_date
        data:
          value: "{{ states('sensor.heruwinterstartdate') }}"
      - service: input_text.set_value
        target:
          entity_id: input_text.heru_summer_start_date
        data:
          value: "{{ states('sensor.herusummerstartdate') }}"


      - service: input_select.select_option
        target:
          entity_id: input_select.heru_regulation_mode
        data:
          option: "{{ state_attr('input_select.heru_regulation_mode','options') [states('sensor.tpheruregulationmode') | int(default=3)] }}"
      - service: input_select.select_option
        target:
          entity_id: input_select.heru_changeover_type
        data:
          option: "{{ state_attr('input_select.heru_changeover_type','options') [states('sensor.tpheruchangeovertype') | int(default=1)] }}"





  - id: start_heru_overpressure_timer
    alias: 'Start Heru forceringstimer'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: switch.heruoverpressuremode
        from: 'off'
        to: 'on'
    condition: []
    action:
      - service: timer.start
        data:
          entity_id: timer.heruoverpressureduration
          duration: "{{ states('sensor.heruoverpressureduration') | int(default=0) * 60 }}"
      - condition: state
        entity_id: switch.heruboostmode
        state: 'on'
      - service: switch.turn_off
        data:
          entity_id: switch.heruboostmode

  - id: cancel_heru_overpressure_timer
    alias: 'StÀng av Heru forceringstimer'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: switch.heruoverpressuremode
        to: 'off'
    condition: []
    action:
      - service: timer.cancel
        data:
          entity_id: timer.heruoverpressureduration

  - id: start_heru_boost_timer
    alias: 'Start Heru övertryckstimer'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: switch.heruboostmode
        from: 'off'
        to: 'on'
    condition: []
    action:
      - service: timer.start
        data:
          entity_id: timer.heruboostduration
          duration: "{{ states('sensor.heruboostduration') | int(default=0) * 60 }}"
      - condition: state
        entity_id: switch.heruoverpressuremode
        state: 'on'
      - service: switch.turn_off
        data:
          entity_id: switch.heruoverpressuremode

  - id: cancel_heru_boost_timer
    alias: 'StÀng av Heru övertryckstimer'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: switch.heruboostmode
        to: 'off'
    condition: []
    action:
      - service: timer.cancel
        data:
          entity_id: timer.heruboostduration

  - id: heru_regulation_mode
    alias: 'RegleringslÀge'
    initial_state: 'on'
    description: 'RegleringslÀge: tilluft, frÄnluft, rum, frÄnluft s/v eller rum s/v'
    trigger:
      - platform: state
        entity_id: input_select.heru_regulation_mode
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 11
          value: "{{ state_attr(trigger.entity_id,'options').index(states(trigger.entity_id)) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.tpheruregulationmode
  - id: update_heru_regulation_mode_input_select
    alias: 'Uppdatera Heru regleringslÀge input_select'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.tpheruregulationmode
    condition: []
    action:
      service: input_select.select_option
      target:
        entity_id: input_select.heru_regulation_mode
      data:
        option: "{{ state_attr('input_select.heru_regulation_mode','options') [states(trigger.entity_id) | int(default=3)] }}"

  - id: heru_changeover_type
    alias: 'Heru vÀxlingsmetod s/v'
    initial_state: 'on'
    description: 'VĂ€xlingsmetod: sommar/vinter'
    trigger:
      - platform: state
        entity_id: input_select.heru_changeover_type
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 51
          value: "{{ state_attr(trigger.entity_id,'options').index(states(trigger.entity_id)) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.tpheruchangeovertype
  - id: update_heru_changeover_type_input_select
    alias: 'Uppdatera Heru vÀxlingsmetod s/v input_select'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.tpheruchangeovertype
    condition: []
    action:
      service: input_select.select_option
      target:
        entity_id: input_select.heru_changeover_type
      data:
        option: "{{ state_attr('input_select.heru_changeover_type','options') [states(trigger.entity_id) | int(default=1)] }}"

  - id: heru_winter_start_date
    alias: 'Heru vinter startdatum'
    initial_state: 'on'
    description: 'Skriv datum dÄ vintern anses ha startat till Heru'
    trigger:
      - platform: state
        entity_id: input_text.heru_winter_start_date
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 56
          value: '{{ states.input_text.heru_winter_start_date.state.split("/")[1]|int * 100 + states.input_text.heru_winter_start_date.state.split("/")[0]|int }}'
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.tpheruwinterstartdate
  - id: update_heru_winter_start_date_input_text
    alias: 'Uppdatera Heru vinter startdatum input_text'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.heruwinterstartdate
    condition: []
    action:
      service: input_text.set_value
      target:
        entity_id: input_text.heru_winter_start_date
      data:
        value: "{{ states(trigger.entity_id) }}"

  - id: heru_summer_start_date
    alias: 'Heru sommar startdatum'
    initial_state: 'on'
    description: 'Skriv datum dÄ sommar anses ha startat till Heru'
    trigger:
      - platform: state
        entity_id: input_text.heru_summer_start_date
    condition: []
    action:
      - service: modbus.write_register
        data:
          hub: heru
          unit: 1
          address: 57
          value: '{{ states.input_text.heru_summer_start_date.state.split("/")[1]|int * 100 + states.input_text.heru_summer_start_date.state.split("/")[0]|int }}'
      - service: homeassistant.update_entity
        data:
          entity_id: sensor.tpherusummerstartdate
  - id: update_heru_summer_start_date_input_text
    alias: 'Uppdatera Heru sommar startdatum input_text'
    initial_state: 'on'
    trigger:
      - platform: state
        entity_id: sensor.herusummerstartdate
    condition: []
    action:
      service: input_text.set_value
      target:
        entity_id: input_text.heru_summer_start_date
      data:
        value: "{{ states(trigger.entity_id) }}"



script:
  write_register_turn_on_bit:
    mode: single
    sequence:
      - service: modbus.write_register
        data:
          hub: "{{ hub }}"
          unit: "{{ unit }}"
          address: "{{ address }}"
          value: "{{ states(sensor_value) | int(default=0) | bitwise_or(2 ** (bit | int - 1)) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: "{{ sensor_value }}"

  write_register_turn_off_bit:
    mode: single
    sequence:
      - service: modbus.write_register
        data:
          hub: "{{ hub }}"
          unit: "{{ unit }}"
          address: "{{ address }}"
          value: "{{ states(sensor_value) | int(default=0) | bitwise_and(65535 - (2 ** (bit | int - 1))) }}"
      - service: homeassistant.update_entity
        data:
          entity_id: "{{ sensor_value }}"

Wow this is a great work!! I am clueless and this is all Greek to međŸ˜”â€đŸ’« but Im using switches for som functions like boost so on. Not so happy as it is not a permanent solution, Östberg said they are considering working on an API but it is not confirmed as to when they will really start.

It seems like you are working on a big project😃 i will copy your code and looking forward to see your final workđŸ«ĄđŸ˜€

2 Likes

Wow thanks!
I was researching this for weeks now. Finally I got my modbus registers working thanks to your post.

1 Like