Alright, so I really needed a second ModBus device data. I decided the easiest route would be to run a separate instance of HA in Docker, have that read the ModBus values from my Sunny Boy, then publish MQTT messages with the values that I need.
Here is the configuration of the HA instance used to do the above:
homeassistant:
name: Sunny Boy Sensors
latitude: !secret home_latitude
longitude: !secret home_longitude
elevation: !secret home_elevation
unit_system: metric
time_zone: !secret home_time_zone
customize: !include customize.yaml
customize_glob: !include customize_global.yaml
config:
#frontend:
mqtt:
broker: !secret mqtt_url
port: !secret mqtt_port
modbus:
type: tcp
host: !secret sma_sb_ip
port: !secret sma_sb_port
#http:
#conversation:
#history:
#recorder:
#logbook:
sensor:
- platform: modbus
scan_interval: 15
registers:
- name: Modbus SB Daily Yield
unit_of_measurement: kWh
slave: 3
register: 30517
count: 4
data_type: int
scale: 0.001
precision: 3
- name: Modbus SB Total Yield
unit_of_measurement: kWh
slave: 3
register: 30513
count: 4
data_type: int
scale: 0.001
precision: 3
- name: Modbus SB PV Power
unit_of_measurement: W
slave: 3
register: 30775
count: 2
data_type: uint
- name: Modbus SB Grid Power
unit_of_measurement: W
slave: 3
register: 30865
count: 2
data_type: uint
- name: Modbus SB Grid Feed
unit_of_measurement: W
slave: 3
register: 30867
count: 2
data_type: uint
- platform: template
sensors:
modbus_sb_pv_production:
friendly_name: 'PV Output'
value_template: >-
{% if states('sensor.modbus_sb_pv_power')|float < 10000 %}
{{ states('sensor.modbus_sb_pv_power') }}
{% else %}
0
{% endif %}
unit_of_measurement: "W"
modbus_sb_total_power:
friendly_name: 'Total consumption'
unit_of_measurement: "W"
value_template: '{{ (((states.sensor.modbus_sb_grid_power.state | float) +
(states.sensor.modbus_sb_pv_production.state | float))) }}'
automation:
- id: mqtt_publish_sb
alias: "MQTT Publish Sunny Boy"
trigger:
- platform: state
entity_id: "sensor.modbus_sb_grid_power"
action:
- service: mqtt.publish
data_template:
topic: "sma/sb"
payload: '{"grid_feed":{{ states("sensor.modbus_sb_grid_feed") }}, "grid_consumption":{{ states("sensor.modbus_sb_grid_power") }}, "production":{{ states("sensor.modbus_sb_pv_production") }}, "daily_yield":{{ states("sensor.modbus_sb_daily_yield") }}, "total_yield":{{ states("sensor.modbus_sb_total_yield") }}}'
Here is the MQTT message:
{"grid_feed":0, "grid_consumption":1819, "production":0, "daily_yield":15.884, "total_yield":248.245}
Here are the MQTT sensors in my normal HA instance:
- platform: mqtt
name: "MQTT SB Daily Yield"
state_topic: "sma/sb"
value_template: '{{ value_json["daily_yield"] }}'
force_update: true
retain: true
unit_of_measurement: "kWh"
- platform: mqtt
name: "MQTT SB Total Yield"
state_topic: "sma/sb"
value_template: '{{ value_json["total_yield"] }}'
force_update: true
retain: true
unit_of_measurement: "kWh"
- platform: mqtt
name: "MQTT SB Production"
state_topic: "sma/sb"
value_template: '{{ value_json["production"] }}'
force_update: true
retain: true
unit_of_measurement: "W"
- platform: mqtt
name: "MQTT SB Grid Feed"
state_topic: "sma/sb"
value_template: '{{ value_json["grid_feed"] }}'
force_update: true
retain: true
unit_of_measurement: "W"
- platform: mqtt
name: "MQTT SB Grid Consumption"
state_topic: "sma/sb"
value_template: '{{ value_json["grid_consumption"] }}'
force_update: true
retain: true
unit_of_measurement: "W"
This works really well. The Docker container uses 32MB ram and does not use much processing. This may help someone else who is trying to do the same. Of course, this would not work to change the state of a coil or write data to ModBus, but it’s a working solution to read ModBus sensors on multiple hubs.