Skip to content

Instantly share code, notes, and snippets.

@tkuennen
Created November 15, 2022 20:26
Show Gist options
  • Save tkuennen/bfae2138572ffce6835965be4efcbaaf to your computer and use it in GitHub Desktop.
Save tkuennen/bfae2138572ffce6835965be4efcbaaf to your computer and use it in GitHub Desktop.
# Victron modbus connection
modbus:
- name: camper-victron
type: tcp
host: 1.2.3.4
port: 502
sensors:
- name: System DC Load
unit_of_measurement: 'W'
device_class: power
slave: 100 # System
address: 860
data_type: int16
scan_interval: 10
lazy_error_count: 3
- name: Battery Runtime Remaining
slave: 100 # System
address: 846
data_type: uint16
scan_interval: 10
lazy_error_count: 3
- name: BMV Battery Level
unit_of_measurement: '%'
slave: 226 # BMV-712
address: 266
data_type: uint16
scale: 0.1
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: BMV Battery Health
unit_of_measurement: '%'
slave: 226 # BMV-712
address: 304
data_type: uint16
scale: 0.1
scan_interval: 10
lazy_error_count: 3
- name: BMV Battery Current
unit_of_measurement: 'A'
device_class: current
slave: 226 # BMV-712
address: 261
data_type: int16
scale: 0.1
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: BMV Battery Voltage
unit_of_measurement: 'V'
device_class: voltage
slave: 226 # BMV-712
address: 259
data_type: uint16
scale: 0.01
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: BMV Truck Battery Voltage
unit_of_measurement: 'V'
device_class: voltage
slave: 226 # BMV-712
address: 260
data_type: uint16
scale: 0.01
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: BMV Battery Discharged Energy
unit_of_measurement: 'kWh'
device_class: energy
state_class: total_increasing
slave: 226 # BMV-712
address: 301
data_type: uint16
scale: 0.1
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: BMV Battery Charged Energy
unit_of_measurement: 'kWh'
device_class: energy
state_class: total_increasing
slave: 226 # BMV-712
address: 302
data_type: uint16
scale: 0.1
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: MPPT Battery Temperature
unit_of_measurement: 'C'
device_class: temperature
slave: 224 # MPPT 100/30
address: 773
data_type: int16
scale: 0.1
scan_interval: 10
lazy_error_count: 3
- name: MPPT Solar Power
unit_of_measurement: 'W'
device_class: power
state_class: measurement
slave: 224 # MPPT 100/30
address: 789
data_type: uint16
scale: 0.1
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: MPPT Solar Panel Current
unit_of_measurement: 'A'
device_class: current
slave: 224 # MPPT 100/30
address: 777
data_type: int16
scale: 0.1
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: MPPT Solar Panel Voltage
unit_of_measurement: 'V'
device_class: voltage
slave: 224 # MPPT 100/30
address: 776
data_type: uint16
scale: 0.01
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: MPPT Solar Charger State
slave: 224 # MPPT 100/30
address: 775
data_type: uint16
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Input Voltage
unit_of_measurement: 'V'
device_class: voltage
slave: 227 # MultiPlus
address: 3
data_type: uint16
scale: 0.1
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Input Current
unit_of_measurement: 'A'
device_class: current
slave: 227 # MultiPlus
address: 6
data_type: int16
scale: 0.1
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Input Frequency
unit_of_measurement: 'Hz'
device_class: frequency
slave: 227 # MultiPlus
address: 9
data_type: int16
scale: 0.01
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Input Power
unit_of_measurement: 'W'
device_class: power
slave: 227 # MultiPlus
address: 12
data_type: int16
scale: 10
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Output Voltage
unit_of_measurement: 'V'
device_class: voltage
slave: 227 # MultiPlus
address: 15
data_type: uint16
scale: 0.1
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Output Current
unit_of_measurement: 'A'
device_class: current
slave: 227 # MultiPlus
address: 18
data_type: int16
scale: 0.1
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Output Frequency
unit_of_measurement: 'Hz'
device_class: frequency
slave: 227 # MultiPlus
address: 21
data_type: int16
scale: 0.01
precision: 1
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Active Input Current Limit
unit_of_measurement: 'A'
device_class: current
slave: 227 # MultiPlus
address: 22
data_type: int16
scale: 0.1
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Output Power
unit_of_measurement: 'W'
device_class: power
slave: 227 # MultiPlus
address: 23
data_type: int16
scale: 10
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Battery Voltage
unit_of_measurement: 'V'
device_class: voltage
slave: 227 # MultiPlus
address: 26
data_type: uint16
scale: 0.01
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Battery Current
unit_of_measurement: 'A'
device_class: current
slave: 227 # MultiPlus
address: 27
data_type: int16
scale: 0.1
precision: 2
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Active Input
slave: 227 # MultiPlus
address: 29
data_type: uint16
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus State
slave: 227 # MultiPlus
address: 31
data_type: uint16
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Error
slave: 227 # MultiPlus
address: 32
data_type: uint16
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Switch Position
slave: 227 # MultiPlus
address: 33
data_type: uint16
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Low Battery Alarm
slave: 227 # MultiPlus
address: 35
data_type: uint16
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: MultiPlus Overload Alarm
slave: 227 # MultiPlus
address: 36
data_type: uint16
precision: 0
scan_interval: 10
lazy_error_count: 3
- name: Victron Interior Temperature Raw
unit_of_measurement: °C
device_class: temperature
slave: 28 # Interior Ruuvi
address: 3304
data_type: int16
scale: 0.01
precision: 1
scan_interval: 60
lazy_error_count: 3
# Ruuvi humidity/temperature sensors are not being exposed via modbus properly at the current time
# - name: Victron Interior Humidity
# unit_of_measurement: '%'
# device_class: humidity
# slave: 28 # Interior Ruuvi
# address: 3306
# data_type: uint16
# scale: 0.1
# precision: 1
# scan_interval: 60
# lazy_error_count: 3
# - name: Victron Interior Pressure
# unit_of_measurement: hPa
# device_class: pressure
# slave: 28 # Interior Ruuvi
# address: 3308
# data_type: uint16
# precision: 1
# scan_interval: 60
# lazy_error_count: 3
- name: Victron Outside Temperature Raw
unit_of_measurement: °C
device_class: temperature
slave: 29 # Outside Ruuvi
address: 3304
data_type: int16
scale: 0.01
precision: 1
scan_interval: 60
lazy_error_count: 3
- name: Victron Plumbing Temperature Raw
unit_of_measurement: °C
device_class: temperature
slave: 30 # Plumbing Ruuvi
address: 3304
data_type: int16
scale: 0.01
precision: 1
scan_interval: 60
lazy_error_count: 3
- name: Victron Freezer Temperature Raw
unit_of_measurement: °C
device_class: temperature
slave: 31 # Freezer Ruuvi
address: 3304
data_type: int16
scale: 0.01
precision: 1
scan_interval: 60
lazy_error_count: 3
- name: Victron Fridge Temperature Raw
unit_of_measurement: °C
device_class: temperature
slave: 32 # Fridge Ruuvi
address: 3304
data_type: int16
scale: 0.01
precision: 1
scan_interval: 60
lazy_error_count: 3
template:
- sensor:
- name: Battery Discharged Energy
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.bmv_battery_discharged_energy') }}"
- name: Battery Charged Energy
unit_of_measurement: 'kWh'
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.bmv_battery_charged_energy') }}"
- name: Multiplus Active Input Text
state: >
{% if is_state('sensor.multiplus_active_input', '0') %}
AC Input 1
{% elif is_state('sensor.multiplus_active_input', '1') %}
AC Input 2
{% elif is_state('sensor.multiplus_active_input', '240') %}
Disconnected
{% else %}
Unknown
{% endif %}
icon: >
{% if is_state('sensor.multiplus_active_input', '0') %}
mdi:toggle-switch
{% elif is_state('sensor.multiplus_active_input', '1') %}
mdi:toggle-switch
{% elif is_state('sensor.multiplus_active_input', '240') %}
mdi:toggle-switch-off-outline
{% else %}
mdi:help
{% endif %}
- name: MPPT Solar Charger State Text
state: >
{% if is_state('sensor.mppt_solar_charger_state', '0') %}
Off
{% elif is_state('sensor.mppt_solar_charger_state', '2') %}
Fault
{% elif is_state('sensor.mppt_solar_charger_state', '3') %}
Bulk
{% elif is_state('sensor.mppt_solar_charger_state', '4') %}
Absorption
{% elif is_state('sensor.mppt_solar_charger_state', '5') %}
Float
{% elif is_state('sensor.mppt_solar_charger_state', '6') %}
Storage
{% elif is_state('sensor.mppt_solar_charger_state', '7') %}
Equalize
{% elif is_state('sensor.mppt_solar_charger_state', '11') %}
Other
{% elif is_state('sensor.mppt_solar_charger_state', '252') %}
External Control
{% else %}
Unknown
{% endif %}
icon: >
{% if is_state('sensor.mppt_solar_charger_state', '0') %}
mdi:toggle-switch-off-outline
{% elif is_state('sensor.mppt_solar_charger_state', '2') %}
mdi:exclamation
{% elif is_state('sensor.mppt_solar_charger_state', '3') %}
mdi:battery-charging-low
{% elif is_state('sensor.mppt_solar_charger_state', '4') %}
mdi:battery-charging-medium
{% elif is_state('sensor.mppt_solar_charger_state', '5') %}
mdi:battery-charging-high
{% elif is_state('sensor.mppt_solar_charger_state', '6') %}
mdi:battery-high
{% elif is_state('sensor.mppt_solar_charger_state', '7') %}
mdi:battery-check-outline
{% elif is_state('sensor.mppt_solar_charger_state', '11') %}
mdi:asterisk
{% elif is_state('sensor.mppt_solar_charger_state', '252') %}
mdi:open-in-new
{% else %}
mdi:help
{% endif %}
- name: Multiplus Switch Position Text
state: >
{% if is_state('sensor.multiplus_switch_position', '1') %}
Charger Only
{% elif is_state('sensor.multiplus_switch_position', '2') %}
Inverter Only
{% elif is_state('sensor.multiplus_switch_position', '3') %}
Inverter/Charger
{% elif is_state('sensor.multiplus_switch_position', '4') %}
Off
{% else %}
Unknown
{% endif %}
icon: >
{% if is_state('sensor.multiplus_switch_position', '1') %}
mdi:transmission-tower-import
{% elif is_state('sensor.multiplus_switch_position', '2') %}
mdi:transmission-tower-export
{% elif is_state('sensor.multiplus_switch_position', '3') %}
mdi:transmission-tower
{% elif is_state('sensor.multiplus_switch_position', '4') %}
mdi:toggle-switch-off-outline
{% else %}
mdi:help
{% endif %}
- name: Multiplus State Text
state: >
{% if is_state('sensor.multiplus_state', '0') %}
Off
{% elif is_state('sensor.multiplus_state', '1') %}
Low Power
{% elif is_state('sensor.multiplus_state', '2') %}
Fault
{% elif is_state('sensor.multiplus_state', '3') %}
Bulk
{% elif is_state('sensor.multiplus_state', '4') %}
Absorption
{% elif is_state('sensor.multiplus_state', '5') %}
Float
{% elif is_state('sensor.multiplus_state', '6') %}
Storage
{% elif is_state('sensor.multiplus_state', '7') %}
Equalize
{% elif is_state('sensor.multiplus_state', '8') %}
Passthrough
{% elif is_state('sensor.multiplus_state', '9') %}
Inverting
{% elif is_state('sensor.multiplus_state', '10') %}
Power Assist
{% elif is_state('sensor.multiplus_state', '11') %}
Power Supply
{% elif is_state('sensor.multiplus_state', '252') %}
Bulk Protection
{% else %}
Unknown
{% endif %}
icon: >
{% if is_state('sensor.multiplus_state', '0') %}
mdi:toggle-switch-off-outline
{% elif is_state('sensor.multiplus_state', '1') %}
mdi:battery-arrow-down
{% elif is_state('sensor.multiplus_state', '2') %}
mdi:exclamation
{% elif is_state('sensor.multiplus_state', '3') %}
mdi:battery-charging-low
{% elif is_state('sensor.multiplus_state', '4') %}
mdi:battery-charging-medium
{% elif is_state('sensor.multiplus_state', '5') %}
mdi:battery-charging-high
{% elif is_state('sensor.multiplus_state', '6') %}
mdi:battery-high
{% elif is_state('sensor.multiplus_state', '7') %}
mdi:battery-check-outline
{% elif is_state('sensor.multiplus_state', '8') %}
mdi:electric-switch-closed
{% elif is_state('sensor.multiplus_state', '9') %}
mdi:transmission-tower-export
{% elif is_state('sensor.multiplus_state', '10') %}
mdi:transmission-tower-import
{% elif is_state('sensor.multiplus_state', '11') %}
mdi:home-battery
{% elif is_state('sensor.multiplus_state', '252') %}
mdi:battery-alert
{% else %}
mdi:help
{% endif %}
- name: Multiplus Overload Alarm Text
state: >
{% if is_state('sensor.multiplus_overload_alarm', '0') %}
Ok
{% elif is_state('sensor.multiplus_overload_alarm', '1') %}
Warning
{% elif is_state('sensor.multiplus_overload_alarm', '2') %}
Alarm
{% else %}
Unknown
{% endif %}
icon: >
{% if is_state('sensor.multiplus_overload_alarm', '0') %}
mdi:checkbox-marked-circle
{% elif is_state('sensor.multiplus_overload_alarm', '1') %}
mdi:alert
{% elif is_state('sensor.multiplus_overload_alarm', '2') %}
mdi:alert-octagon
{% else %}
mdi:help
{% endif %}
- name: Multiplus Low Battery Alarm Text
state: >
{% if is_state('sensor.multiplus_low_battery_alarm', '0') %}
Ok
{% elif is_state('sensor.multiplus_low_battery_alarm', '1') %}
Warning
{% elif is_state('sensor.multiplus_low_battery_alarm', '2') %}
Alarm
{% else %}
Unknown
{% endif %}
icon: >
{% if is_state('sensor.multiplus_low_battery_alarm', '0') %}
mdi:checkbox-marked-circle
{% elif is_state('sensor.multiplus_low_battery_alarm', '1') %}
mdi:alert
{% elif is_state('sensor.multiplus_low_battery_alarm', '2') %}
mdi:alert-octagon
{% else %}
mdi:help
{% endif %}
- name: Battery Runtime Remaining (formatted)
state: >
{% set time = states.sensor.battery_runtime_remaining.state | int %}
{% set minutes = (((time / 36) % 1) * 60) | int %}
{% set hours = ((time % 864) / 36) | int %}
{% set days = (time / 864) | int %}
{%- if time == 0 -%}
Charging
{%- else -%}
{%- if days > 0 -%}
{{ days }} Days {{ hours }} Hours {{ minutes }} Minutes
{%- else -%}
{{ hours }} Hours {{ minutes }} Minutes
{%- endif -%}
{%- endif -%}
- name: Battery Runtime Remaining (hours)
state: >
{% set time = states.sensor.battery_runtime_remaining.state | int %}
{% set hours = (time / 36) | round(1) %}
{%- if time == 0 -%}
240.0
{%- else -%}
{{ hours }}
{%- endif -%}
unit_of_measurement: h
- name: Sun Elevation
state: >
{%- if state_attr("sun.sun", "elevation") >= 0 %}
{{ state_attr("sun.sun", "elevation") }}
{%- else %}
0.0
{%- endif %}
unit_of_measurement: '°'
sensor:
# Integrations to get kWh measurements for shore power and solar power
- platform: integration
source: sensor.multiplus_input_power
name: MultiPlus Input Power Consumed
unit_prefix: k
round: 2
method: left
- platform: integration
source: sensor.mppt_solar_power
name: MPPT Solar Power Yield
unit_prefix: k
round: 2
method: left
# Attempt to filter out big swings for Ruuvi sensors that seem to happen on startup
- platform: filter
name: Victron Interior Temperature
entity_id: sensor.victron_interior_temperature_raw
unique_id: victron-interior-temperature
filters:
- filter: outlier
window_size: 4
radius: 5.0
- platform: filter
name: Victron Outside Temperature
entity_id: sensor.victron_outside_temperature_raw
unique_id: victron-outside-temperature
filters:
- filter: outlier
window_size: 4
radius: 5.0
- platform: filter
name: Victron Plumbing Temperature
entity_id: sensor.victron_plumbing_temperature_raw
unique_id: victron-plumbing-temperature
filters:
- filter: outlier
window_size: 4
radius: 5.0
- platform: filter
name: Victron Freezer Temperature
entity_id: sensor.victron_freezer_temperature_raw
unique_id: victron-freezer-temperature
filters:
- filter: outlier
window_size: 4
radius: 5.0
- platform: filter
name: Victron Fridge Temperature
entity_id: sensor.victron_fridge_temperature_raw
unique_id: victron-fridge-temperature
filters:
- filter: outlier
window_size: 4
radius: 5.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment