I am currently testing intra hour trading opportunities of upto 15ct/kWh, within the whole hour! It is an obvious missed opportunity not to be able to see those visualized on the dashboard. And the advanced page custom graphs have their own limitations, I failed to find ways to reconstruct anything comparable to the dashboard DESS graphs and even then they do not display the forecasted data.
And I am clueless how you managed to generate the graphs above. I guess something external, and thus yet another learning curve to climb?
Iām getting that info via MQTT from my GX device and itās being recorded and visualized by HomeAssistant.
To give you an idea, these are my sensor definitions, but iirc there is also a dedicated plugin/integration that will create such entities automatically:
- sensor:
- unique_id: mp2_battery_power
name: "Batterie Leistung"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/Dc/0/Power"
value_template: "{{ value_json.value }}"
state_class: measurement
unit_of_measurement: "W"
device_class: "power"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_bat_voltage
name: "Batterie Spannung"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/Dc/0/Voltage"
value_template: "{{ value_json.value }}"
state_class: measurement
unit_of_measurement: "V"
device_class: "voltage"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_bat_current
name: "Batterie Strom"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/Dc/0/Current"
value_template: "{{ value_json.value }}"
state_class: measurement
unit_of_measurement: "A"
device_class: "current"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_soc
name: "Batterie SoC"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/Soc"
value_template: "{{ value_json.value }}"
state_class: measurement
unit_of_measurement: "%"
device_class: "battery"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_dess_target_soc
name: "Batterie DESS Target SoC"
state_topic: "venus/N/xxxsecret_idxxxx/settings/0/Settings/DynamicEss/Schedule/0/Soc"
value_template: "{{ value_json.value }}"
state_class: measurement
unit_of_measurement: "%"
device_class: "battery"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_powerin
name: "Batterie Energie geladen"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/History/ChargedEnergy"
value_template: "{{ value_json.value }}"
state_class: total_increasing
unit_of_measurement: "kWh"
device_class: "energy"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_powerout
name: "Batterie Energie entladen"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/History/DischargedEnergy"
value_template: "{{ value_json.value }}"
state_class: total_increasing
unit_of_measurement: "kWh"
device_class: "energy"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_min_cell_voltage
name: "Batterie Min Zellspannung"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/System/MinCellVoltage"
value_template: "{{ value_json.value }}"
state_class: measurement
unit_of_measurement: "V"
device_class: "voltage"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_max_cell_voltage
name: "Batterie Max Zellspannung"
state_topic: "venus/N/xxxsecret_idxxxx/battery/512/System/MaxCellVoltage"
value_template: "{{ value_json.value }}"
state_class: measurement
unit_of_measurement: "V"
device_class: "voltage"
device:
name: "mp2"
identifiers: "mp2"
- unique_id: mp2_dess_reactive_strategy
name: "DESS Strategy num"
state_topic: "venus/N/xxxsecret_idxxxx/system/0/DynamicEss/ReactiveStrategy"
value_template: "{{ value_json.value }}"
device:
name: "mp2"
identifiers: "mp2"
# - unique_id: mp2_dess_final_strategy
# name: "DESS Final Strategy"
# state_topic: "venus/N/xxxsecret_idxxxx/system/0/DynamicEss/FinalStrategy"
# value_template: "{{ value_json.value }}"
# device:
# name: "mp2"
# identifiers: "mp2"
- name: "DESS Strategy"
unique_id: "mp2_dess_reactive_strategy_txt"
state: >
{% set mapper = {
'1': 'SCHEDULED_SELFCONSUME',
'2': 'SCHEDULED_CHARGE_ALLOW_GRID',
'3': 'SCHEDULED_CHARGE_ENHANCED',
'4': 'SELFCONSUME_ACCEPT_CHARGE',
'5': 'IDLE_SCHEDULED_FEEDIN',
'6': 'SCHEDULED_DISCHARGE',
'7': 'SELFCONSUME_ACCEPT_DISCHARGE',
'8': 'IDLE_MAINTAIN_SURPLUS',
'9': 'IDLE_MAINTAIN_TARGETSOC',
'10': 'SCHEDULED_CHARGE_SMOOTH_TRANSITION',
'11': 'SCHEDULED_CHARGE_FEEDIN',
'12': 'SCHEDULED_CHARGE_NO_GRID',
'13': 'SCHEDULED_MINIMUM_DISCHARGE',
'14': 'SELFCONSUME_NO_GRID',
'15': 'IDLE_NO_OPPORTUNITY',
'16': 'UNSCHEDULED_CHARGE_CATCHUP_TARGETSOC',
'17': 'SELFCONSUME_INCREASED_DISCHARGE',
'18': 'KEEP_BATTERY_CHARGED',
'19': 'SCHEDULED_DISCHARGE_SMOOTH_TRANSITION',
'20': 'SELF_CONSUME_ACCEPT_BELOW_TSOC',
'21': 'IDLE_NO_DISCHARGE_OPPORTUNITY',
'92': 'DESS_DISABLED',
'93': 'SELFCONSUME_UNEXPECTED_EXCEPTION',
'94': 'SELFCONSUME_FAULTY_CHARGERATE',
'95': 'UNKNOWN_OPERATING_MODE',
'96': 'ESS_LOW_SOC',
'97': 'SELFCONSUME_UNMAPPED_STATE',
'98': 'SELFCONSUME_UNPREDICTED',
'99': 'NO_WINDOW'} %}
{% set state = states('sensor.mp2_dess_reactive_strategy') %}
{{ mapper[state] if state in mapper else 'Unknown' }}
- number:
#ESS Grid Setpoint
- name: "Grid Setpoint"
unique_id: "mp2_grid_setpoint"
state_topic: "venus/N/xxxsecret_idxxxx/settings/0/Settings/CGwacs/AcPowerSetPoint"
command_topic: "venus/W/xxxsecret_idxxxx/settings/0/Settings/CGwacs/AcPowerSetPoint"
command_template: '{"value": {{ value }} }'
value_template: '{{ (value_json.value) | round(0) }}'
unit_of_measurement: "W"
device_class: power
device:
name: "mp2"
identifiers: "mp2"
mode: "box"
icon: mdi:transmission-tower
min: -10000
max: 10000
step: 10
#ESS Max Inverter Power
- name: "Max Discharge Power"
unique_id: "mp2_discharge_power"
state_topic: "venus/N/xxxsecret_idxxxx/settings/0/Settings/CGwacs/MaxDischargePower"
command_topic: "venus/W/xxxsecret_idxxxx/settings/0/Settings/CGwacs/MaxDischargePower"
command_template: '{"value": {{ value }} }'
value_template: '{{ (value_json.value) | round(0) }}'
mode: "box"
unit_of_measurement: "W"
device_class: power
device:
name: "mp2"
identifiers: "mp2"
icon: mdi:battery-charging-low
min: -1
max: 3000
step: 1
#ESS Max Battery Charge Power
- name: "Max Charge Power"
unique_id: "mp2_charge_power"
state_topic: "venus/N/xxxsecret_idxxxx/settings/0/Settings/CGwacs/MaxChargePower"
command_topic: "venus/W/xxxsecret_idxxxx/settings/0/Settings/CGwacs/MaxChargePower"
command_template: '{"value": {{ value }} }'
value_template: '{{ (value_json.value) | round(0) }}'
mode: "box"
unit_of_measurement: "W"
device_class: power
device:
name: "mp2"
identifiers: "mp2"
icon: mdi:battery-charging-high
min: -1
max: 2000
step: 1
- name: "Min SoC"
unique_id: "mp2_min_soc"
state_topic: "venus/N/xxxsecret_idxxxx/settings/0/Settings/CGwacs/BatteryLife/MinimumSocLimit"
command_topic: "venus/W/xxxsecret_idxxxx/settings/0/Settings/CGwacs/BatteryLife/MinimumSocLimit"
command_template: '{"value": {{ value }} }'
value_template: '{{ (value_json.value) | round(0) }}'
mode: "box"
unit_of_measurement: "%"
device:
name: "mp2"
identifiers: "mp2"
icon: mdi:percent
min: 5
max: 100
step: 1
- name: "DESS System Efficiency"
unique_id: "mp2_dess_system_efficiency"
state_topic: "venus/N/xxxsecret_idxxxx/settings/0/Settings/DynamicEss/SystemEfficiency"
command_topic: "venus/W/xxxsecret_idxxxx/settings/0/Settings/DynamicEss/SystemEfficiency"
command_template: '{"value": {{ value }} }'
value_template: '{{ (value_json.value) | round(0) }}'
mode: "box"
unit_of_measurement: "%"
device:
name: "mp2"
identifiers: "mp2"
icon: mdi:percent
min: 50.0
max: 100.0
step: 1.0
- select:
#Multiplus Modus
- name: Inverter Mode
unique_id: mp2_inverter_mode
state_topic: "venus/N/xxxsecret_idxxxx/vebus/275/Mode"
value_template: >
{% set value = value_json.value %}
{% if value == 1 %}
Charger only
{% elif value == 2 %}
Inverter only
{% elif value == 3 %}
On
{% elif value == 4 %}
Off
{% else %}
Error - No Data
{% endif %}
options:
- "Charger only"
- "Inverter only"
- "On"
- "Off"
command_topic: "venus/W/xxxsecret_idxxxx/vebus/275/Mode"
command_template: >
{% set value_map = {
"Charger only": 1,
"Inverter only": 2,
"On": 3,
"Off": 4,
}
%}
{"value":{{ value_map[value] }}}
device:
name: "mp2"
identifiers: "mp2"
I was afraid youād say somethink like that HomeAssistant, awell, not the worst tool to add to the immer growing toolbox I guess.
BjoernK
(Bjƶrn Kellermann)
2 October 2025 21:09
47
@dognose
I assume Victron spend a lot of resources into DESS and in many cases it is doing what is supposed to do. But with flexibility of Victron systems there might be many edge cases.
Maybe Victron could extends its open nature and create a āmarketplaceā for custom/community algorithms. The plugin from the marketplace could be executed on Venus OS (to offload costs) and could use APIs.
I would suggest four plugins with according APIs.
Price forecast
PV forecast
Load forecast
Scheduler/ DESS
Each plugin should be free selectable, either Victron, NodeRed or market place. I could provide my own load forecast and DESS would use it. Or I use Victronās forecasts but use a custom scheduler.
Selecting either Victron or NodeRed might be a MVP for custom plugins.
Example for a rule I would implement:
If 7-days PV forecast is lower than 7-days lforecast, then switch off DESS/restrict selling to grid. I did this today for my location in Hamburg/Germany. DESS green mode would have sold at this evening peak at 20ct and maybe two days later used from grid at 39ct.
My system might be an edge case with as 8kWp PV, āhugeā 56kWh battery and 12 kWh consumption per day (plus optional manageable loads substituting gas).
1 Like
Ersus
3 October 2025 10:28
48
But isnāt it already that open so you can develop your own system to manage your Victron gear like SmartgridOne ā Smartgrid Solutions does?
BjoernK
(Bjƶrn Kellermann)
3 October 2025 15:34
49
Both. Victron can be remote controlled via MQTT, ModBus or NodeRed.
Maybe I have missed the API to get load forecast and OV forecast while DESS is switched of.
The idea is to be able to customize single elements while using the rest out of stock.
In a second step, the community could share best algorithms, though Victron only needs to provide the framework freeing resources for other development while providing superior experience for their customers.