modbus:
  - name: victron_gx
    type: tcp
    host: 192.168.103.30
    port: 502
    timeout: 3
    delay: 2
    lazy_error_count: 10
    sensors:
      # ---- SOLAR CHARGER (Unit ID 226) ----
      - name: Solar Voltage
        slave: 226
        address: 776
        input_type: holding
        data_type: uint16
        scale: 0.01
        precision: 2
        unit_of_measurement: "V"
        device_class: voltage
        state_class: measurement

      - name: Solar Amperage
        slave: 226
        address: 777
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "A"
        device_class: current
        state_class: measurement

      - name: Solar Wattage
        slave: 226
        address: 789
        input_type: holding
        data_type: uint16
        scale: 0.1
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement

      - name: Solar Yield Today
        slave: 226
        address: 784
        input_type: holding
        data_type: uint16
        scale: 0.1
        precision: 3
        unit_of_measurement: "kWh"
        device_class: energy
        state_class: total

      # DC system
      - name: DC Voltage
        slave: 100
        address: 840
        input_type: holding
        data_type: uint16
        scale: 0.1
        precision: 2
        unit_of_measurement: "V"
        device_class: voltage
        state_class: measurement
        unique_id: dc_voltage

      - name: DC Wattage
        slave: 100
        address: 860
        input_type: holding
        data_type: int16
        scale: 1
        precision: 0
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        unique_id: dc_wattage

      # GPS (Slave ID 100)
      - name: GPS Latitude ID 100
        slave: 100
        address: 2800
        input_type: holding
        data_type: int32
        scale: 0.0000001
        precision: 7
        state_class: measurement
        unique_id: gps_latitude_id_100

      - name: GPS Longitude ID 100
        slave: 100
        address: 2802
        input_type: holding
        data_type: int32
        scale: 0.0000001
        precision: 7
        state_class: measurement
        unique_id: gps_longitude_id_100

      - name: GPS Course ID 100
        slave: 100
        address: 2804
        input_type: holding
        data_type: uint16
        scale: 0.01
        precision: 2
        unit_of_measurement: "°"
        state_class: measurement
        unique_id: gps_course_id_100

      - name: GPS Speed ID 100
        slave: 100
        address: 2805
        input_type: holding
        data_type: uint16
        scale: 0.01
        precision: 2
        unit_of_measurement: "m/s"
        state_class: measurement
        unique_id: gps_speed_id_100

      - name: GPS Fix ID 100
        slave: 100
        address: 2806
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: gps_fix_id_100

      - name: GPS Satellites ID 100
        slave: 100
        address: 2807
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: gps_satellites_id_100

      - name: GPS Altitude ID 100
        slave: 100
        address: 2808
        input_type: holding
        data_type: int32
        scale: 0.16
        precision: 1
        unit_of_measurement: "m"
        state_class: measurement
        unique_id: gps_altitude_id_100

      # GPS (Unit ID 1)
      - name: GPS Latitude ID 1
        slave: 1
        address: 2800
        input_type: holding
        data_type: int32
        scale: 0.0000001
        precision: 7
        state_class: measurement
        unique_id: gps_latitude_id_1

      - name: GPS Longitude ID 1
        slave: 1
        address: 2802
        input_type: holding
        data_type: int32
        scale: 0.0000001
        precision: 7
        state_class: measurement
        unique_id: gps_longitude_id_1

      - name: GPS Course ID 1
        slave: 1
        address: 2804
        input_type: holding
        data_type: uint16
        scale: 0.01
        precision: 2
        unit_of_measurement: "°"
        state_class: measurement
        unique_id: gps_course_id_1

      - name: GPS Speed ID 1
        slave: 1
        address: 2805
        input_type: holding
        data_type: uint16
        scale: 0.01
        precision: 2
        unit_of_measurement: "m/s"
        state_class: measurement
        unique_id: gps_speed_id_1

      - name: GPS Fix ID 1
        slave: 1
        address: 2806
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: gps_fix_id_1

      - name: GPS Satellites ID 1
        slave: 1
        address: 2807
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: gps_satellites_id_1

      - name: GPS Altitude ID 1
        slave: 1
        address: 2808
        input_type: holding
        data_type: int32
        scale: 0.16
        precision: 1
        unit_of_measurement: "m"
        state_class: measurement
        unique_id: gps_altitude_id_1

      # ---- CHARGER (Unit ID 223) ----
      - name: Charger Output 1 Voltage
        slave: 223
        address: 2307
        input_type: holding
        data_type: uint16
        scale: 0.01
        precision: 2
        unit_of_measurement: "V"
        device_class: voltage
        state_class: measurement
        unique_id: charger_output_1_voltage

      - name: Charger Output 1 Current
        slave: 223
        address: 2308
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "A"
        device_class: current
        state_class: measurement
        unique_id: charger_output_1_current

      - name: Charger Output 1 Temperature
        slave: 223
        address: 2309
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
        unique_id: charger_output_1_temperature

      - name: Charger AC Current
        slave: 223
        address: 2314
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "A"
        device_class: current
        state_class: measurement
        unique_id: charger_ac_current

      - name: Charger AC Current Limit
        slave: 223
        address: 2316
        input_type: holding
        data_type: int16
        scale: 0.1
        precision: 1
        unit_of_measurement: "A"
        device_class: current
        state_class: measurement
        unique_id: charger_ac_current_limit

      - name: Charger On Off Raw
        slave: 223
        address: 2317
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: charger_on_off_raw

      - name: Charger Charge State Raw
        slave: 223
        address: 2318
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: charger_charge_state_raw

      - name: Charger Error Code
        slave: 223
        address: 2319
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: charger_error_code

      - name: Charger Relay State
        slave: 223
        address: 2320
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: charger_relay_state

      - name: Charger Low Voltage Alarm
        slave: 223
        address: 2321
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: charger_low_voltage_alarm

      - name: Charger High Voltage Alarm
        slave: 223
        address: 2322
        input_type: holding
        data_type: uint16
        scale: 1
        state_class: measurement
        unique_id: charger_high_voltage_alarm

template:
  - sensor:
      # GPS aggregation: prefer slave 100, fall back to slave 1
      - name: GPS Latitude
        unique_id: gps_latitude
        state_class: measurement
        state: >-
          {% set v100 = states('sensor.gps_latitude_id_100') %}
          {% set v1 = states('sensor.gps_latitude_id_1') %}
          {% if v100 not in ['unavailable', 'unknown'] and v100 | float(0) != 0 %}
            {{ v100 }}
          {% elif v1 not in ['unavailable', 'unknown'] and v1 | float(0) != 0 %}
            {{ v1 }}
          {% else %}
            {{ v100 }}
          {% endif %}

      - name: GPS Longitude
        unique_id: gps_longitude
        state_class: measurement
        state: >-
          {% set v100 = states('sensor.gps_longitude_id_100') %}
          {% set v1 = states('sensor.gps_longitude_id_1') %}
          {% if v100 not in ['unavailable', 'unknown'] and v100 | float(0) != 0 %}
            {{ v100 }}
          {% elif v1 not in ['unavailable', 'unknown'] and v1 | float(0) != 0 %}
            {{ v1 }}
          {% else %}
            {{ v100 }}
          {% endif %}

      - name: GPS Course
        unique_id: gps_course
        unit_of_measurement: "°"
        state_class: measurement
        state: >-
          {% set v100 = states('sensor.gps_course_id_100') %}
          {% set v1 = states('sensor.gps_course_id_1') %}
          {% if v100 not in ['unavailable', 'unknown'] %}
            {{ v100 }}
          {% elif v1 not in ['unavailable', 'unknown'] %}
            {{ v1 }}
          {% else %}
            {{ v100 }}
          {% endif %}

      - name: GPS Speed
        unique_id: gps_speed
        unit_of_measurement: "m/s"
        state_class: measurement
        state: >-
          {% set v100 = states('sensor.gps_speed_id_100') %}
          {% set v1 = states('sensor.gps_speed_id_1') %}
          {% if v100 not in ['unavailable', 'unknown'] %}
            {{ v100 }}
          {% elif v1 not in ['unavailable', 'unknown'] %}
            {{ v1 }}
          {% else %}
            {{ v100 }}
          {% endif %}

      - name: GPS Fix
        unique_id: gps_fix
        state_class: measurement
        state: >-
          {% set v100 = states('sensor.gps_fix_id_100') %}
          {% set v1 = states('sensor.gps_fix_id_1') %}
          {% if v100 not in ['unavailable', 'unknown'] and v100 | int(0) > 0 %}
            {{ v100 }}
          {% elif v1 not in ['unavailable', 'unknown'] and v1 | int(0) > 0 %}
            {{ v1 }}
          {% else %}
            {{ v100 }}
          {% endif %}

      - name: GPS Satellites
        unique_id: gps_satellites
        state_class: measurement
        state: >-
          {% set v100 = states('sensor.gps_satellites_id_100') %}
          {% set v1 = states('sensor.gps_satellites_id_1') %}
          {% if v100 not in ['unavailable', 'unknown'] and v100 | int(0) > 0 %}
            {{ v100 }}
          {% elif v1 not in ['unavailable', 'unknown'] and v1 | int(0) > 0 %}
            {{ v1 }}
          {% else %}
            {{ v100 }}
          {% endif %}

      - name: GPS Altitude
        unique_id: gps_altitude
        unit_of_measurement: "m"
        state_class: measurement
        state: >-
          {% set v100 = states('sensor.gps_altitude_id_100') %}
          {% set v1 = states('sensor.gps_altitude_id_1') %}
          {% if v100 not in ['unavailable', 'unknown'] %}
            {{ v100 }}
          {% elif v1 not in ['unavailable', 'unknown'] %}
            {{ v1 }}
          {% else %}
            {{ v100 }}
          {% endif %}

      - name: Charger On Off
        state: >-
          {% set v = states('sensor.charger_on_off_raw')|int %}
          {{ {0:'Off',1:'On',2:'Error',3:'Unavailable'}.get(v, 'Unknown') }}

      - name: Charger Charge State
        state: >-
          {% set v = states('sensor.charger_charge_state_raw')|int %}
          {{ {
            0:'Off',1:'Low Power',2:'Fault',3:'Bulk',4:'Absorption',5:'Float',
            6:'Storage',7:'Equalize/Manual',8:'External Control'
          }.get(v,'Unknown') }}

      - name: "Charger DC Wattage"
        unique_id: charger_dc_wattage
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement
        state: >-
          {% set v = states('sensor.charger_output_1_voltage')|float(0) %}
          {% set a = states('sensor.charger_output_1_current')|float(0) %}
          {{ (v * a) | round(1) }}

  - binary_sensor:
      - name: Charger Low Voltage Alarm Active
        state: "{{ states('sensor.charger_low_voltage_alarm')|int == 2 }}"
      - name: Charger High Voltage Alarm Active
        state: "{{ states('sensor.charger_high_voltage_alarm')|int == 2 }}"

sensor:
  - platform: integration
    source: sensor.dc_wattage
    name: DC System Energy
    unit_prefix: k
    round: 2
    method: trapezoidal
    max_sub_interval:
      minutes: 5

  - platform: integration
    source: sensor.solar_wattage
    name: Solar Yield
    unit_prefix: k
    round: 2
    method: trapezoidal
    max_sub_interval:
      minutes: 5

  - platform: integration
    source: sensor.charger_dc_wattage
    name: DC Charger Energy
    unit_prefix: k
    round: 2
    method: trapezoidal
    max_sub_interval:
      minutes: 5

utility_meter:
  dc_load_energy_daily:
    source: sensor.dc_system_energy
    cycle: daily

  dc_load_energy_monthly:
    source: sensor.dc_system_energy
    cycle: monthly

  solar_yield_daily:
    source: sensor.solar_yield
    cycle: daily

  solar_yield_monthly:
    source: sensor.solar_yield
    cycle: monthly

  charger_dc_wattage_daily:
    source: sensor.dc_charger_energy
    cycle: daily

  charger_dc_wattage_monthly:
    source: sensor.dc_charger_energy
    cycle: monthly
