From 335682e25b4c6f6f0dcf2efa6fbdd5c713dbcd23 Mon Sep 17 00:00:00 2001 From: fboundy Date: Sun, 27 Nov 2022 15:29:02 +0000 Subject: [PATCH] v1.1.0 --- .gitignore | 2 + inputs.yaml | 43 +++++++++++ scripts.yaml | 179 ++++++++++++++++++++++++++++++++++++++++++++ solis-template.yaml | 140 ++++++++++++++++++++++++---------- umodbus_scan.py | 6 +- umodbus_test.py | 14 ++++ 6 files changed, 344 insertions(+), 40 deletions(-) create mode 100644 .gitignore create mode 100644 inputs.yaml create mode 100644 scripts.yaml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6873db9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +deleted_from_storgae.txt +umodbus_scan.py diff --git a/inputs.yaml b/inputs.yaml new file mode 100644 index 0000000..ec2148a --- /dev/null +++ b/inputs.yaml @@ -0,0 +1,43 @@ +input_boolean: + trigger_first_morning: + name: Waiting for first morning motion + icon: mdi:kettle + + solis_eco7_charging: + name: Solis Eco7 Charging + icon: mdi:flash + + saver_session: + name: Saver Session + icon: mdi:transmission-tower + + solis_storage_mode_grid_charge: + name: Solis Storage Mode - Grid Charge + + solis_storage_mode_backup: + name: Solis Storage Mode - Backup + + solis_storage_mode_wake_up: + name: Solis Storage Mode - Wake-Up + + solis_storage_mode_timed: + name: Solis Storage Mode - Timed + + solis_storage_mode_off_grid: + name: Solis Storage Mode - Off-Grid + + solis_storage_mode_spontaneous: + name: Solis Storage Mode - Spontaneous + +input_datetime: + economy_7_start: + name: Economy 7 Start + has_date: false + has_time: true + icon: mdi:clock-digital + + economy_7_end: + name: Economy 7 End + has_date: false + has_time: true + icon: mdi:clock-digital diff --git a/scripts.yaml b/scripts.yaml new file mode 100644 index 0000000..8120805 --- /dev/null +++ b/scripts.yaml @@ -0,0 +1,179 @@ +set_solis_storage_toggles: + alias: Set Solis Storage Toggles + sequence: + - if: + - condition: template + value_template: + "{{states('sensor.solis_energy_storage_control_switch') | + int | bitwise_and(32) == 32}}" + then: + - service: input_boolean.turn_on + data: {} + target: + entity_id: + - input_boolean.solis_storage_mode_grid_charge + else: + - service: input_boolean.turn_off + data: {} + target: + entity_id: input_boolean.solis_storage_mode_grid_charge + - if: + - condition: template + value_template: + "{{states('sensor.solis_energy_storage_control_switch') | + int | bitwise_and(16) == 16}}" + then: + - service: input_boolean.turn_on + data: {} + target: + entity_id: input_boolean.solis_storage_mode_backup + else: + - service: input_boolean.turn_off + data: {} + target: + entity_id: input_boolean.solis_storage_mode_backup + - if: + - condition: template + value_template: + "{{states('sensor.solis_energy_storage_control_switch') | + int | bitwise_and(8) == 8}}" + then: + - service: input_boolean.turn_on + data: {} + target: + entity_id: input_boolean.solis_storage_mode_wake_up + else: + - service: input_boolean.turn_off + data: {} + target: + entity_id: + - input_boolean.solis_storage_mode_wake_up + - if: + - condition: template + value_template: + "{{states('sensor.solis_energy_storage_control_switch') | + int | bitwise_and(4) == 4}}" + then: + - service: input_boolean.turn_on + data: {} + target: + entity_id: input_boolean.solis_storage_mode_off_grid + else: + - service: input_boolean.turn_off + data: {} + target: + entity_id: input_boolean.solis_storage_mode_off_grid + - if: + - condition: template + value_template: + "{{states('sensor.solis_energy_storage_control_switch') | + int | bitwise_and(2) == 2}}" + then: + - service: input_boolean.turn_on + data: {} + target: + entity_id: + - input_boolean.solis_storage_mode_timed + else: + - service: input_boolean.turn_off + data: {} + target: + entity_id: input_boolean.solis_storage_mode_timed + - if: + - condition: template + value_template: + "{{states('sensor.solis_energy_storage_control_switch') | + int | bitwise_and(1) == 1}}" + then: + - service: input_boolean.turn_on + data: {} + target: + entity_id: input_boolean.solis_storage_mode_spontaneous + else: + - service: input_boolean.turn_off + data: {} + target: + entity_id: + - input_boolean.solis_storage_mode_spontaneous + mode: single + icon: mdi:toggle-switch-off-outline +solis_set_energy_storage_mode: + alias: Solis Set Energy Storage Mode + fields: + storage_mode: + description: Storage Mode to Set (uint16) + example: 35 + sequence: + - service: script.solis_write_holding_register + data: + register_addr: 43110 + register_value: + "{{(states('input_boolean.solis_storage_mode_spontaneous') + == 'on') | int + 2 * (states('input_boolean.solis_storage_mode_timed') + == 'on') | int + 4 * (states('input_boolean.solis_storage_mode_off_grid') + == 'on') | int + 8 * (states('input_boolean.solis_storage_mode_wake_up') + == 'on') | int + 16 * (states('input_boolean.solis_storage_mode_backup') + == 'on') | int + 32 * (states('input_boolean.solis_storage_mode_grid_charge') + == 'on') | int }}" + mode: single +solis_set_charge_current: + alias: Solis Set Charge Current + fields: + solis_set_charge_current: + description: Fixed time charge current (A) + example: 50 + sequence: + - service: script.solis_write_holding_register + data: + register_addr: 43141 + register_value: "{{ charge_current * 10 }}" + mode: single +solis_write_holding_register: + alias: Solis Write Holding Register + fields: + register_addr: + description: Holding address to write to + example: 43141 + register_value: + description: Value to write to holding address + example: 500 + sequence: + - service: modbus.write_register + data: + address: "{{ register_addr }}" + slave: 1 + value: "{{ register_value }}" + hub: solis + - service: logbook.log + data: + message: Send {{register_value}} to {{register_addr}} + name: Solis Write +solis_set_eco7_times: + alias: Solis Set Eco7 Times + sequence: + - service: script.solis_write_holding_register + data: + register_addr: 43143 + register_value: + "{{(states('input_datetime.economy_7_start')).split(':')[0] + | int}}" + - service: script.solis_write_holding_register + data: + register_addr: 43144 + register_value: + "{{(states('input_datetime.economy_7_start')).split(':')[1] + | int}}" + - service: script.solis_write_holding_register + data: + register_addr: 43145 + register_value: + "{{(states('input_datetime.economy_7_end')).split(':')[0] + | int}}" + - service: script.solis_write_holding_register + data: + register_addr: 43146 + register_value: + "{{(states('input_datetime.economy_7_end')).split(':')[1] + | int}}" + mode: single + icon: mdi:battery-clock-outline diff --git a/solis-template.yaml b/solis-template.yaml index 0353f45..c5c6f52 100644 --- a/solis-template.yaml +++ b/solis-template.yaml @@ -1,38 +1,102 @@ -sensor: - - name: "Solis Grid Active Power (Negative)" - unique_id: "Solis Grid Active Power (Negative)" - unit_of_measurement: W - device_class: power - state_class: measurement - state: >- - {{ -1 * states('sensor.solis_grid_active_power') | float }} - - - name: "Solis Grid Export Power" - unique_id: "Solis Grid Export Power" - unit_of_measurement: W - device_class: power - state_class: measurement - state: >- - {% set state = states.sensor.solis_grid_active_power.state | float %} - {{ state if state > 0 else 0 }} - - - name: "Solis Grid Import Power" - unique_id: "Solis Grid Import Power" - unit_of_measurement: W - device_class: power - state_class: measurement - state: >- - {% set state = states.sensor.solis_grid_active_power.state | float %} - {{ -1 * state if state < 0 else 0 }} - - - name: "Solis Grid Mode" - unique_id: "Solis Grid Mode" - state: >- - {% set state = states.sensor.solis_grid_active_power.state | float %} - {{ 'Import' if state < 0 else 'Export' }} - - - name: "Solis Battery Mode" - unique_id: "Solis Battery Mode" - state: >- - {% set state = states.sensor.solis_battery_current_direction.state | float %} - {{ 'Discharge' if state > 0 else 'Charge' }} +template: + - sensor: + - name: "Solis Grid Active Power (Negative)" + unique_id: "Solis Grid Active Power (Negative)" + unit_of_measurement: W + device_class: power + state_class: measurement + state: >- + {{ -1 * states('sensor.solis_grid_active_power') | float }} + + - name: "Solis Grid Export Power" + unique_id: "Solis Grid Export Power" + unit_of_measurement: W + device_class: power + state_class: measurement + state: >- + {% set state = states.sensor.solis_grid_active_power.state | float %} + {{ state if state > 0 else 0 }} + + - name: "Solis Grid Import Power" + unique_id: "Solis Grid Import Power" + unit_of_measurement: W + device_class: power + state_class: measurement + state: >- + {% set state = states.sensor.solis_grid_active_power.state | float %} + {{ -1 * state if state < 0 else 0 }} + + - name: "Solis Grid Mode" + unique_id: "Solis Grid Mode" + state: >- + {% set state = states.sensor.solis_grid_active_power.state | float %} + {% if state > 50 -%} + Export + {%- elif state <-50 -%} + Import + {%- else -%} + Zero + {%- endif %} + + - name: "Solis Battery Mode" + unique_id: "Solis Battery Mode" + state: >- + {% set state = states.sensor.solis_battery_current_direction.state | int %} + {{ 'Discharge' if state > 0 else 'Charge' }} + + - name: "Solis Manual Storage Mode" + unique_id: "Solis Manual Storage Mode" + state: >- + {{(states('input_boolean.solis_storage_mode_spontaneous') == 'on') | int + + 2 * (states('input_boolean.solis_storage_mode_timed') == 'on') | int + + 4 * (states('input_boolean.solis_storage_mode_off_grid') == 'on') | int + + 8 * (states('input_boolean.solis_storage_mode_wake_up') == 'on') | int + + 16 * (states('input_boolean.solis_storage_mode_backup') == 'on') | int + + 32 * (states('input_boolean.solis_storage_mode_grid_charge') == 'on') | int + }} + + - name: "Solis Eco7 Hours Remaining" + unique_id: "Solis Eco7 Time Remaining" + state_class: measurement + state: >- + {% if today_at(states('input_datetime.economy_7_end')) < now() -%} + {{(((today_at(states('input_datetime.economy_7_end')) - + today_at(states('input_datetime.economy_7_start')))).total_seconds() / 36) | int / 100}} + {%- else -%} + {{max((((today_at(states('input_datetime.economy_7_end')) - + max(now(), today_at(states('input_datetime.economy_7_start')))).total_seconds() / 36) | int) / 100,0)}} + {%- endif %} + + - name: "Solis Eco7 Charge Current" + unique_id: "Solis Eco7 Charge Current" + device_class: current + state_class: measurement + unit_of_measurement: A + state: >- + {{( + ((states('input_number.solis_battery_capacity') | int * 1000) * + ((states('sensor.solis_opt_target_soc') | int) - (states('sensor.solis_battery_soc') | int)) + ) + / 10 + / + (states('sensor.solis_eco7_time_remaining') | float) + / (states('sensor.solis_battery_voltage_bms') | float) ) | int / 10 + }} + + - name: "Solis Battery Charge Power" + unique_id: "Solis Battery Charge Power" + device_class: power + state_class: measurement + unit_of_measurement: W + state: >- + {% set state = states.sensor.solis_battery_current_direction.state | int %} + {{ 0 if state > 0 else states('sensor.solis_battery_power') | float(2) }} + + - name: "Solis Battery Discharge Power" + unique_id: "Solis Battery Discharge Power" + device_class: power + state_class: measurement + unit_of_measurement: W + state: >- + {% set state = states.sensor.solis_battery_current_direction.state | int %} + {{ states('sensor.solis_battery_power') | float(2) if state > 0 else 0 }} diff --git a/umodbus_scan.py b/umodbus_scan.py index 276477c..f5f8556 100644 --- a/umodbus_scan.py +++ b/umodbus_scan.py @@ -8,6 +8,7 @@ import socket from umodbus import conf from umodbus.client import tcp +from time import sleep # configuration CFG_IP = "192.168.4.79" # Update with your inverter IP @@ -19,10 +20,11 @@ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((CFG_IP, CFG_PORT)) -for addrs in range(33000, 33300, 10): - message = tcp.read_input_registers(slave_id=1, starting_address=addrs, quantity=10) +for addrs in range(33215, 33300): + message = tcp.read_input_registers(slave_id=1, starting_address=addrs, quantity=1) response = tcp.send_message(message, sock) print(f"{addrs:8d}: {response}") + # sleep(1) sock.close() # %% diff --git a/umodbus_test.py b/umodbus_test.py index abe1c68..bd65f20 100644 --- a/umodbus_test.py +++ b/umodbus_test.py @@ -35,6 +35,20 @@ "scale": 1, "uom": "%", }, + { + "desc": "Battery Storage Mode (W)", + "addrs": 43110, + "len": 1, + "scale": 1, + "uom": "", + }, + { + "desc": "Battery Storage Mode (R)", + "addrs": 33132, + "len": 1, + "scale": 1, + "uom": "", + }, ] # Enable values to be signed (default is False).