The reset seems to be happening every hour based on the logs of SMA UI (see below)
All settings have been applied manually in the SMA UI (except the resets which have been happening automagically)
The reset seems to be happening every hour based on the logs of SMA UI (see below)
All settings have been applied manually in the SMA UI (except the resets which have been happening automagically)
The shell commands are doing what you would do when you log in via a browsers using the inverter IP adress to manually do this:
If you go into your browser and do this, you can open your console. Under the ānetworkā option (at least in Firefox) you can see these commands being set and their respective IDs.
I also have a Home Manager 2.0, so SMA is handling the zero export, with the annoying side effect of auto-resetting randomly to no power limitation at the grid connection point.
I have the below automations (I use the UI, because I like to use it to do some sanity checks on the code, adapt as required if you want to plug it into your automations.yaml).
1) Ensure SMA stays correctly configured:
alias: SMA inverter GCP config corrector
description: >-
Periodically puts inverter back into correct mode, as SMA automatically
disables it by itself
triggers:
- entity_id: sensor.current_electricity_market_price
trigger: state
- value_template: |-
{{ states('sensor.current_electricity_market_price') | float(0) < 0 and
states('sensor.power_at_grid_connection_point') | float(0) < -100 }} #trigger when grid connection is lower than -100 (that means SMA switched of the GCP function by itself)
trigger: template
conditions:
- condition: numeric_state
entity_id: sensor.current_electricity_market_price
below: input_number.dynamic_price_limit
actions:
- response_variable: auth_response
data: {}
action: shell_command.sma_authenticate
- variables:
login_successful: >- # AI wrote this, as the code posted previously didn't work for me. It works, but don't ask me how
{% set success = false %} {% if auth_response is defined and
auth_response.returncode == 0 and auth_response.stdout is defined %}
{% set cleaned_stdout = auth_response.stdout | trim %}
{% if cleaned_stdout %} {# Ensure cleaned_stdout is not empty before parsing #}
{% set parsed_json = cleaned_stdout | from_json %}
{% if parsed_json is mapping %}
{% set result_val = parsed_json.get('result') %}
{% if result_val is mapping %}
{% set sid_val_check = result_val.get('sid') %}
{% if sid_val_check is defined and sid_val_check | string | length > 0 %}
{% set success = true %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %} {{ success }}
extracted_sid: >-
{% set sid_val = "" %} {% if auth_response is defined and
auth_response.returncode == 0 and auth_response.stdout is defined %}
{% set cleaned_stdout_for_sid = auth_response.stdout | trim %}
{% if cleaned_stdout_for_sid %} {# Ensure cleaned_stdout_for_sid is not empty before parsing #}
{% set parsed_json_for_sid = cleaned_stdout_for_sid | from_json %}
{% if parsed_json_for_sid is mapping %}
{% set result_val_for_sid = parsed_json_for_sid.get('result') %}
{% if result_val_for_sid is mapping %}
{% set sid_from_get = result_val_for_sid.get('sid') %}
{% if sid_from_get is defined %}
{% set sid_val = sid_from_get | string %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %} {{ sid_val }}
- choose:
- conditions:
- condition: template
value_template: "{{ login_successful == 'True' or login_successful == true }}"
sequence:
- target:
entity_id: input_text.sma_session_id
data:
value: "{{ extracted_sid }}"
action: input_text.set_value
- data:
sid: "{{ extracted_sid }}"
payload: "{\"destDev\":[],\"values\":[{\"6800_0892D600\":{\"1\":[2137]}}]}"
action: shell_command.sma_set_grid_power_limit_gcp
- data:
sid: "{{ extracted_sid }}"
action: shell_command.sma_logout
mode: single
2) Control limit slider automatically depending on day-ahead price:
alias: Price based inverter control
description: >-
Adjusts SMA power limit slider based on electricity market price, and aims for
zero grid export/import when prices are low using the GCP power limit setting
of pysmaplus integration
triggers:
- entity_id: sensor.current_electricity_market_price
id: price_change
trigger: state
- entity_id: input_boolean.dynamic_control_toggle
id: toggle_change
trigger: state
conditions: []
actions:
- choose:
- conditions:
- condition: template
value_template: "{{ not is_dynamic_control_on }}"
sequence:
- data:
value: 100
target:
entity_id: input_number.sma_power_limit_slider
action: input_number.set_value
- conditions:
- condition: template
value_template: "{{ is_dynamic_control_on }}"
sequence:
- choose:
- conditions:
- condition: template
value_template: "{{ current_price > dynamic_price_limit }}"
sequence:
- data:
value: 100
target:
entity_id: input_number.sma_power_limit_slider
action: input_number.set_value
- conditions:
- condition: template
value_template: "{{ current_price < dynamic_price_limit }}"
sequence:
- data:
value: 0
target:
entity_id: input_number.sma_power_limit_slider
action: input_number.set_value
mode: single
variables:
dynamic_price_limit: "{{ states(\"input_number.dynamic_price_limit\") | float(0) }}"
current_price: "{{ states(\"sensor.current_electricity_market_price\") | float(0) }}"
is_dynamic_control_on: "{{ is_state(\"input_boolean.dynamic_control_toggle\", \"on\") }}"
current_sma_limit_slider: "{{ states(\"input_number.sma_power_limit_slider\") | float(100) }}"
3) Set the correct value whenever limit slider changes in SMA using pysmaplus integration
alias: SMA Power Limit Pysma GCP
description: Set SMA power limit using PysmaPlus integration
triggers:
- entity_id: input_number.sma_power_limit_slider
trigger: state
conditions:
- condition: state
entity_id: input_boolean.sma_power_limit_pysmaplus_automation_enabled
state: "on"
actions:
- data:
entity_id: sensor.stp10_0_3av_40_947_active_power_limitation_gcp
value: "{{ states('input_number.sma_power_limit_slider') | float(0) * 100 }}" #change the 100 depending on your inverter nominal power (I have 10kW)
action: pysmaplus.set_value
mode: single
Shell commands in configuration.yaml (as posted before):
put your inverter IP and password where required.
shell_command:
sma_authenticate: >
curl -k -H 'Content-Type:application/json' -H "Accept: application/json" -X POST -d '{"right":"istl","pass":"YOURINSTALLERPASSWORD"}' https://YOURINVERTERIP/dyn/login.json
sma_logout: >-
curl -k -H 'Content-Type: application/json' -X POST -d '{}' 'https://YOURINVERTERIP/dyn/logout.json?sid={{sid}}'
sma_set_grid_power_limit: >-
curl -k -H 'Content-Type: application/json' -X POST -d '{{payload}}' 'https://YOURINVERTERIP/dyn/setParamValues.json?sid={{sid}}'
sma_get_grid_power_limit: >-
curl -k -H 'Content-Type: application/json' -X POST -d '{{payload}}' 'https://YOURINVERTERIP/dyn/getAllParamValues.json?sid={{sid}}'
sma_set_grid_power_limit_gcp: >-
curl -k -H 'Content-Type: application/json' -X POST -d '{{payload}}' 'https://YOURINVERTERIP/dyn/setParamValues.json?sid={{sid}}'
Hi,
I am new in this environment, but since I have a SMA Sunny Tripower X 25 with Home Manager 2.0 running with Ennexos I would like to use Your impressive work. My aim is also to avoid Grid delivery when prices are low.
I tried adding the adjusted programming to automations.yaml, but I am qurious to where the sensor.current_electricity_market_price gets the price?
Is it Nord pool?
BR / Jan
Really cool to see all the automations! Going to continue/improve my setup with these shared insights soon.
@baecklund.jan I use the EnergyZero device for all energy pricing related sensors. This matches my dynamic contact of my energy provider. Adding it through HA is 10 seconds of work.
I have a SMA Tripower 8.0 and after some research, Iāve found a way to limit the power without writing to registers that are located in flash: SMA warns against cyclically writing to most registers, except a few in the sunspec modbus interface. (https://sunspec.org/wp-content/uploads/2025/01/SunSpec-Modbus-IEEE-1547-2018-Profile-Specification-and-Implementation-Guide-v1.1-1.pdf)
Access to the sunspec modbus (as opposed to the direct SMA modbus interface) is over slave address 126 (when the device address in the modbus setup is set to 3). The register to control is 40349 (40348 in Home Assistant) and contains the power as a percentage of the max power. 0 is off, 10000 is 100% The factor 1.25 for raw_power is the result of this calculation: (required_power / 8000)*10000 to map the required power on the scale from 0 to 10000 with a max power of 8000W.
With some AI assistance, this automation came out, is tested and seems 100% functional:
alias: limit PV power when injection price is negative
description: Dynamic power 8am-8pm, Max power otherwise
triggers:
- minutes: /1
trigger: time_pattern
actions:
- data:
hub: pv_oost-west
slave: 126
address: 40348
value: >
{% set p_pv = states('sensor.pv_avg_power') | float(0) %}
{% set p_net = states('sensor.net_consumption_avg') | float(0) * 1000 %}
{% set ImportPrice = states('sensor.current_electricity_market_price') | float(3) %}
{% set ExportPrice = states('sensor.injectie_current_electricity_market_price') | float(0) %}
{% set is_daytime = today_at("08:00") <= now() <= today_at("20:00") %}
{% if not is_daytime %}
10000
{% elif ImportPrice < 0 %}
0
{% elif ExportPrice > 0 %}
10000
{% else %}
{% set raw_power = (250 + p_pv + p_net) | clamp(0, 8000) %}
{{ (raw_power * 1.25) | int }}
{% endif %}
action: modbus.write_register
mode: restart
Thanks for sharing. Besides activating Modbus, are there any other settings that need to be enabled in the SMA local web interface? Iām using a SUNNY TRIPOWER 10.0, but on my side it doesnāt seem to respond to the register change.
Iāve (re)discovered @swante ās GitHub - littleyoda/ha-pysmaplus: home assistant custom integration for pysma-plus Ā· GitHub and I now successfully set limit, stop and start my SMA Tripower 4.0 using webconnect (with installer password) and firmware 4.10.10R.
It does require Home Assistant Community Store and please please make a backup before starting. Adding SMA Device Plus will make duplicate entities because the serial number is the same. On succes, consider restoring the backup and remove the SMA integration first and setting this up properly.
You might also have a ātoo much sessionsā error if you have too many tabs open or poll to often.
The Operator Mode value to start is 1467 (or 295) and to stop is 381. The automation is simple⦠if mode is 1467 and price < 0 set and production high, then set mode to 381 and vice versa.
It could be that different values are needed based on your country settings.
Ps the documentation is being updated Update documentation, Operation Mode: MPP/Start on SMA Default = 295 for Tripower Firmware version: 4.10.10.R Ā· Issue #106 Ā· littleyoda/ha-pysmaplus Ā· GitHub. If you have different operator mode values, why not share ![]()
Thanks for the tip.
Iāve tried that integration tto, but I cannot get it to communicate with the inverter for some unclear reason. Just writing to one modbus register allows me to deal with it using one less integration ![]()
Iām afraid itās not working on my side due to the setting āOperating mode of active power limitationā not being set to āExternal active power setpointā. Changing this setting requires an SMA Grid Guard code.
Although I can successfully write to and read from the configured register, the active power does not change in real time.
Update: The solution of @johanbos is working at my side. Thanks for sharing your insights!