### Install Project Dependencies Source: https://github.com/kellerza/sunsynk/blob/main/www/README.md Run this command in the project's root directory to install all necessary packages for local development. ```bash npm install ``` -------------------------------- ### Sunsynk Multi options.yaml Configuration Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Example configuration file for the Sunsynk Multi addon. Adjust inverter details and sensor definitions to match your setup. Ensure the MQTT host and port are correctly set. ```yaml --- DRIVER: "pymodbus" INVERTERS: - SERIAL_NR: "007" HA_PREFIX: SS MODBUS_ID: 1 DONGLE_SERIAL_NUMBER: "0" PORT: tcp://mbusd:502 SENSOR_DEFINITIONS: single-phase SENSORS: - energy_management - power_flow_card - pv2_power SENSORS_FIRST_INVERTER: - settings MANUFACTURER: Sunsynk READ_ALLOW_GAP: 2 READ_SENSORS_BATCH_SIZE: 20 SCHEDULES: - KEY: W READ_EVERY: 5 REPORT_EVERY: 60 CHANGE_ANY: false CHANGE_BY: 80 CHANGE_PERCENT: 0 NUMBER_ENTITY_MODE: "auto" MQTT_HOST: core-mosquitto MQTT_PORT: 1883 MQTT_USERNAME: hass MQTT_PASSWORD: "" # DEBUG: 0 # DEBUG_DEVICE: "/dev/ttyAMA0" ``` -------------------------------- ### Install Sunsynk Python Library Source: https://context7.com/kellerza/sunsynk/llms.txt Install the library via pip. Use the `[solarman]` or `[umodbus]` extra to include support for Solarman WiFi dongles or umodbus, respectively. ```bash pip install sunsynk # With Solarman WiFi dongle support: pip install sunsynk[solarman] # With umodbus support: pip install sunsynk[umodbus] ``` -------------------------------- ### Connect and Read Sensors with PySunsynk Source: https://context7.com/kellerza/sunsynk/llms.txt Example of using the `PySunsynk` driver to connect to an inverter via serial RS485, track specific sensors, read their values, and print them. Ensure the correct port and baudrate are used for your setup. ```python from sunsynk.pysunsynk import PySunsynk from sunsynk.definitions.single_phase import SENSORS import asyncio async def main(): # Create the inverter client (pymodbus driver, serial RS485) inv = PySunsynk( port="/dev/ttyUSB0", baudrate=9600, server_id=1, timeout=10, read_sensors_batch_size=20, ) # Select sensors to track sensors_to_read = [ SENSORS.all["battery_soc"], SENSORS.all["battery_voltage"], SENSORS.all["grid_power"], SENSORS.all["load_power"], SENSORS.all["pv_power"], ] inv.state.track(*sensors_to_read) await inv.connect() # Read sensor values from the inverter await inv.read_sensors(sensors_to_read) for sen in sensors_to_read: print(f"{sen.name}: {inv.state[sen]} {sen.unit}") # Example output: # Battery SOC: 85 % # Battery voltage: 52.4 V # Grid power: -320 W # Load power: 1450 W # PV power: 2100 W asyncio.run(main()) ``` -------------------------------- ### Define Custom Sensors in Python Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/mysensors.md Example `mysensors.py` file demonstrating how to initialize `SensorDefinitions` and add custom sensors like basic, math, and read/write types. ```python from sunsynk import AMPS, CELSIUS, KWH, VOLT, WATT, Sensor, SensorDefinitions from sunsynk.rwsensors import NumberRWSensor, SelectRWSensor, TimeRWSensor from sunsynk.sensors import MathSensor, TempSensor # Initialize the sensor definitions SENSORS = SensorDefinitions() # Add your custom sensors SENSORS += ( # Basic sensor example Sensor(178, "My Custom Power Sensor", WATT, -1), # Math sensor example (combining multiple registers) MathSensor((175, 172), "Custom Combined Power", WATT, factors=(1, 1)), # Read/Write sensor example NumberRWSensor(130, "Custom Control Setting", "%", min=0, max=100), ) ``` -------------------------------- ### Run Local VitePress Docs Server Source: https://github.com/kellerza/sunsynk/blob/main/www/README.md Execute this command to start a local development server for the VitePress documentation site. The --port option is optional. ```bash npm run docs:dev ``` -------------------------------- ### Sunsynk Base Inverter Client Example Source: https://context7.com/kellerza/sunsynk/llms.txt Demonstrates how to initialize and use the base `Sunsynk` class to connect to an inverter, track specific sensors, read their values, and print them. ```APIDOC ## `Sunsynk` — Base Inverter Client ### Description The abstract base class managing connection parameters, sensor state, register-batch reading, and sensor writing. Concrete subclasses implement `connect()`, `read_holding_registers()`, and `write_register()`. ### Method Signature ```python from sunsynk.pysunsynk import PySunsynk from sunsynk.definitions.single_phase import SENSORS import asyncio async def main(): # Create the inverter client (pymodbus driver, serial RS485) inv = PySunsynk( port="/dev/ttyUSB0", baudrate=9600, server_id=1, timeout=10, read_sensors_batch_size=20, ) # Select sensors to track sensors_to_read = [ SENSORS.all["battery_soc"], SENSORS.all["battery_voltage"], SENSORS.all["grid_power"], SENSORS.all["load_power"], SENSORS.all["pv_power"], ] inv.state.track(*sensors_to_read) await inv.connect() # Read sensor values from the inverter await inv.read_sensors(sensors_to_read) for sen in sensors_to_read: print(f"{sen.name}: {inv.state[sen]} {sen.unit}") # Example output: # Battery SOC: 85 % # Battery voltage: 52.4 V # Grid power: -320 W # Load power: 1450 W # PV power: 2100 W asyncio.run(main()) ``` ``` -------------------------------- ### SolarmanSunsynk Driver Example Source: https://context7.com/kellerza/sunsynk/llms.txt Shows how to use the `SolarmanSunsynk` driver for inverters connected via a Solarman WiFi dongle, including connection, sensor reading, and disconnection. ```APIDOC ## `SolarmanSunsynk` — Solarman WiFi Dongle Driver ### Description Concrete `Sunsynk` implementation using `pysolarmanv5` for inverters connected via a Solarman WiFi dongle. ### Method Signature ```python from sunsynk.solarmansunsynk import SolarmanSunsynk from sunsynk.definitions.single_phase import SENSORS import asyncio async def main(): inv = SolarmanSunsynk( port="tcp://192.168.1.182:8899", # Dongle local IP and port dongle_serial_number=2712345678, # Found on dongle label or router server_id=1, timeout=10, ) sensors_to_read = [SENSORS.all["battery_soc"], SENSORS.all["pv_power"]] inv.state.track(*sensors_to_read) await inv.connect() await inv.read_sensors(sensors_to_read) print(f"Battery SOC: {inv.state[sensors_to_read[0]]} %") print(f"PV Power: {inv.state[sensors_to_read[1]]} W") await inv.disconnect() asyncio.run(main()) ``` ``` -------------------------------- ### Solarman Driver Configuration Example Source: https://context7.com/kellerza/sunsynk/llms.txt YAML configuration for inverters using the Solarman WiFi dongle. Includes specific settings for the dongle and recommended schedules to prevent overload. ```yaml DRIVER: solarman INVERTERS: - SERIAL_NR: "1234567890" PORT: tcp://192.168.1.182:8899 # Dongle local IP:8899 DONGLE_SERIAL_NUMBER: "2712345678" MODBUS_ID: 1 SENSOR_DEFINITIONS: single-phase SENSORS: - battery_soc - pv_power - grid_power # Recommended schedules for Solarman to avoid dongle overload SCHEDULES: - KEY: W READ_EVERY: 15 REPORT_EVERY: 60 CHANGE_BY: 80 - KEY: rw READ_EVERY: 15 REPORT_EVERY: 60 CHANGE_ANY: true - KEY: any_unit READ_EVERY: 30 REPORT_EVERY: 60 CHANGE_BY: 80 ``` -------------------------------- ### Run Mbusd Docker Container Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Starts the mbusd Docker container. ```bash docker compose up mbusd ``` -------------------------------- ### Lovelace Power Distribution Card YAML Configuration Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/examples/lovelace.md Example Lovelace YAML configuration for the custom power-distribution-card. This setup defines entities for solar, home, battery, pool, and grid power, along with their display properties and actions. ```yaml type: custom:power-distribution-card title: '' entities: - decimals: '' display_abs: true name: solar unit_of_display: W icon: mdi:solar-power producer: true entity: sensor.ss_pv1_power threshold: '' preset: solar icon_color: equal: '' smaller: '' - decimals: '' display_abs: true name: home unit_of_display: W consumer: true icon: mdi:home-assistant invert_value: true entity: sensor.ss_essential_power color_threshold: '0' threshold: '' preset: home icon_color: bigger: '' equal: '' smaller: '' arrow_color: bigger: '' equal: '' smaller: '' - decimals: '' display_abs: true name: battery unit_of_display: W consumer: true icon: mdi:battery-outline producer: true entity: sensor.ss_battery_power threshold: '' preset: battery icon_color: bigger: '' equal: '' smaller: '' secondary_info_attribute: '' battery_percentage_entity: sensor.ss_battery_soc - decimals: '' display_abs: true name: pool unit_of_display: W invert_value: true consumer: true icon: mdi:pool entity: sensor.ss_non_essential_power color_threshold: '0' preset: pool threshold: '' icon_color: bigger: '' equal: '' smaller: '' arrow_color: bigger: '' equal: '' smaller: '' - decimals: '' display_abs: true name: grid unit_of_display: W icon: mdi:transmission-tower entity: sensor.ss_grid_ct_power preset: grid threshold: '' icon_color: equal: '' smaller: '' double_tap_action: action: navigate navigation_path: /lovelace/power tap_action: action: navigate navigation_path: /lovelace/power center: type: bars content: - preset: ratio name: ratio - preset: custom entity: sensor.ss_battery_soc name: SOC animation: slide ``` -------------------------------- ### Connect and Read Sensors with SolarmanSunsynk Source: https://context7.com/kellerza/sunsynk/llms.txt Example of using the `SolarmanSunsynk` driver to connect to an inverter via a Solarman WiFi dongle. Requires the dongle's local IP, port, and serial number. Tracks and reads battery SOC and PV power. ```python from sunsynk.solarmansunsynk import SolarmanSunsynk from sunsynk.definitions.single_phase import SENSORS import asyncio async def main(): inv = SolarmanSunsynk( port="tcp://192.168.1.182:8899", # Dongle local IP and port dongle_serial_number=2712345678, # Found on dongle label or router server_id=1, timeout=10, ) sensors_to_read = [SENSORS.all["battery_soc"], SENSORS.all["pv_power"]] inv.state.track(*sensors_to_read) await inv.connect() await inv.read_sensors(sensors_to_read) print(f"Battery SOC: {inv.state[sensors_to_read[0]]} %") print(f"PV Power: {inv.state[sensors_to_read[1]]} W") await inv.disconnect() asyncio.run(main()) ``` -------------------------------- ### PySunsynk Driver Examples Source: https://context7.com/kellerza/sunsynk/llms.txt Illustrates how to instantiate the `PySunsynk` driver for different connection types (Serial RS485, Modbus TCP, RTU-over-TCP, RTU-over-UDP) and perform raw register read/write operations. ```APIDOC ## `PySunsynk` — PyModbus Driver ### Description Concrete `Sunsynk` implementation using `pymodbus`. Supports serial RS485, Modbus TCP (`tcp://`), RTU-over-TCP (`serial-tcp://`), and UDP variants. ### Method Signature ```python from sunsynk.pysunsynk import PySunsynk # Serial RS485 connection inv_serial = PySunsynk(port="/dev/ttyUSB0", server_id=1) # Modbus TCP gateway (e.g., mbusd) inv_tcp = PySunsynk(port="tcp://192.168.1.100:502", server_id=1) # RTU-over-TCP (for gateways that don't do Modbus TCP translation) inv_rtu_tcp = PySunsynk(port="serial-tcp://192.168.1.100:8899", server_id=1) # RTU-over-UDP inv_rtu_udp = PySunsynk(port="serial-udp://192.168.1.100:8899", server_id=1) async def read_raw_registers(): await inv_tcp.connect() # Read 10 holding registers starting at address 150 regs = await inv_tcp.read_holding_registers(start=150, length=10) print(regs) # e.g. (2304, 0, 1450, 2100, 0, 0, 0, 0, 0, 0) # Write a single register value success = await inv_tcp.write_register(address=103, value=100) print(f"Write {'succeeded' if success else 'failed'}") ``` ``` -------------------------------- ### Custom Sensor with Simple Division Logic Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/mysensors.md Example of a custom sensor class `MyCustomSensor` that divides values from two registers, demonstrating custom logic implementation. ```python from dataclasses import dataclass, field from sunsynk import Sensor, SensorDefinitions, WATT from sunsynk.helpers import unpack_value @dataclass(slots=True, eq=False) class MyCustomSensor(Sensor): """Custom sensor, using multiple registers.""" def reg_to_value(self, regs: RegType) -> ValType: """Calculate the value.""" val1 = unpack_value((regs[0],), signed=True) val2 = unpack_value((regs[1],), signed=True) return val1 / val2 SENSORS = SensorDefinition() # Use the class above with register 10 and 20 SENSORS += MyCustomSensor((10, 20), "Mysensor1", WATT) ``` -------------------------------- ### Custom Selling Load Power Sensor Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/mysensors.md Example of a `MathSensor` to calculate selling load power by subtracting inverter output from CT power. ```python MathSensor((175, 172), "Selling Load Power direct", WATT, factors=(1, 1)), ``` -------------------------------- ### Battery Sensor Schedule Override Example Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/schedules.md Example of overriding the battery sensor schedule to update on all changes and increase the read time to 30 seconds. ```yaml - KEY: "%" READ_EVERY: 30 REPORT_EVERY: 300 CHANGE_ANY: true ``` -------------------------------- ### Install Sunsynk Power Flow Card Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/examples/lovelace.md This snippet shows the basic configuration to enable the Sunsynk Power Flow card. It is typically added to your Home Assistant configuration. ```yaml SENSORS: - power_flow_card ``` -------------------------------- ### Run Sunsynk Multi Docker Container Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Starts the Sunsynk Multi Docker container in detached mode. ```bash docker compose up -d sunsynk-multi ``` -------------------------------- ### Docker Compose Configuration for Sunsynk Multi Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Use this configuration in your `docker-compose.yml` file to run the Sunsynk Multi service. Customize environment variables to match your MQTT broker and inverter setup. ```yaml services: sunsynk-multi-amd64: restart: unless-stopped profiles: ['sunsynk-amd64'] image: ghcr.io/kellerza/hass-addon-sunsynk-multi:stable environment: MQTT_HOST: mqtt MQTT_PORT: 1883 MQTT_USERNAME: ${MQTT_USER} MQTT_PASSWORD: ${MQTT_PASSWORD} S6_KEEP_ENV: 1 DRIVER: "pymodbus" SENSOR_DEFINITIONS: "single-phase" SENSORS: '["energy_management", "power_flow_card", "pv2_power"]' SENSORS_FIRST_INVERTER: '["settings"]' MANUFACTURER: "Sunsynk" READ_ALLOW_GAP: 2 READ_SENSORS_BATCH_SIZE: 20 NUMBER_ENTITY_MODE: "auto" INVERTERS: '[{"SERIAL_NR":"1234567890","HA_PREFIX":"SUN-10k-dsaxz","MODBUS_ID":1,"DONGLE_SERIAL_NUMBER":"1234567890","PORT":"tcp://192.168.1.123:8899"}]' SCHEDULES: '[{"key":"w","read_every":5,"report_every":60,"change_by":80,"change_percent":0,"change_any":0}]' ``` -------------------------------- ### Implement System Time Sensor Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/mysensors.md Defines a custom sensor for reading and writing system time. It includes methods for converting between display values and register values, handling date and time formats. Note that write functionality is partially implemented in this example. ```python from dataclasses import dataclass, field import re from sunsynk import RegType, ValType, SensorDefinitions from sunsynk.rwsensors import RWSensor, ResolveType SENSORS = SensorDefinitions() @dataclass(slots=True, eq=False) class SystemTimeRWSensor(RWSensor): """Read & write time sensor.""" def value_to_reg(self, value: ValType, resolve: ResolveType) -> RegType: """Get the reg value from a display value.""" redt = re.compile(r"(2\d{3})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})") match = redt.fullmatch(value) if not match: raise ValueError("Invalid datetime {value}") y, m, d = int(match.group(1)) - 2000, int(match.group(2)), int(match.group(3)) h, mn, s = int(match.group(4)), int(match.group(5)), int(match.group(6)) regs = ( (y << 8) + m, (d << 8) + h, (mn << 8) + s, ) raise ValueError(f"{y}-{m:02}-{d:02} {h}:{mn:02}:{s:02} ==> {regs}") return regs def reg_to_value(self, regs: RegType) -> ValType: """Decode the register.""" y = ((regs[0] & 0xFF00) >> 8) + 2000 m = regs[0] & 0xFF d = (regs[1] & 0xFF00) >> 8 h = regs[1] & 0xFF mn = (regs[2] & 0xFF00) >> 8 s = regs[2] & 0xFF return f"{y}-{m:02}-{d:02} {h}:{mn:02}:{s:02}" SENSORS += SystemTimeRWSensor((22, 23, 24), "Date", unit="") ``` -------------------------------- ### Include Parallel Inverter Sensors Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/definitions.md Add the 'parallel' group to include sensors used for configuring and managing parallel inverter setups. ```yaml SENSORS: - parallel ``` -------------------------------- ### Load Home Assistant Packages Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/examples/overview.md This configuration snippet loads packages from the `/config/packages/` directory. Ensure this directory exists and contains your package YAML files. ```yaml homeassistant: packages: !include_dir_named packages ``` -------------------------------- ### Build Sunsynk Multi Docker Image Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Builds the Sunsynk Multi Docker image using a specified base image. Replace `` with the appropriate image for your architecture (e.g., Raspberry Pi or 64-bit PC). ```bash BUILD_FROM= docker compose build sunsynk-multi ``` -------------------------------- ### Home Assistant Add-on YAML Configuration Source: https://context7.com/kellerza/sunsynk/llms.txt Complete YAML configuration for the Home Assistant add-on, covering essential options for driver selection, sensor polling, and MQTT settings. ```yaml DRIVER: pymodbus # pymodbus | solarman | umodbus READ_SENSOR_BATCH_SIZE: 20 READ_ALLOW_GAP: 2 INVERTERS: - SERIAL_NR: "1234567890" HA_PREFIX: SS MODBUS_ID: 1 PORT: tcp://homeassistant.local:502 SENSOR_DEFINITIONS: single-phase SENSORS: - battery_soc - battery_voltage - battery_power - grid_power - load_power - pv_power - inverter_state SENSORS_FIRST_INVERTER: - prog1_time - prog1_power - battery_max_charge_current SENSOR_OVERRIDES: - battery_max_charge_current.max=200 - prog4_power.max=4990 SCHEDULES: - KEY: W READ_EVERY: 5 REPORT_EVERY: 60 CHANGE_BY: 80 - KEY: "%" READ_EVERY: 30 REPORT_EVERY: 300 CHANGE_ANY: true - KEY: rw READ_EVERY: 5 REPORT_EVERY: 300 CHANGE_ANY: true MQTT_CUSTOM: false # true to override supervisor-detected MQTT # MQTT_HOST: core-mosquitto # MQTT_PORT: 1883 # MQTT_USERNAME: hass # MQTT_PASSWORD: secret MANUFACTURER: Sunsynk NUMBER_ENTITY_MODE: auto # auto | box | slider PROG_TIME_INTERVAL: 15 DEBUG: 0 # 0=off, 1=filter changes, 2=debug ``` -------------------------------- ### Custom MQTT Configuration Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/multi-options.md Configure custom MQTT settings if not using the Home Assistant Supervisor's defaults. Ensure MQTT_CUSTOM is set to true to force the use of these settings. ```yaml MQTT_CUSTOM: true # Force the add-on to use this MQTT configuration MQTT_HOST: core-mosquitto MQTT_PORT: 1883 MQTT_USERNAME: hass MQTT_PASSWORD: my-secure-password ``` -------------------------------- ### Include All Available Sensors Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/definitions.md Use the 'all' group to include every sensor available for your inverter. This is primarily for testing and not recommended for production due to potential performance impacts on Home Assistant. ```yaml SENSORS: - all ``` -------------------------------- ### View Sunsynk Multi Container Logs Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Follows the logs of the Sunsynk Multi Docker container in real-time. ```bash docker compose logs -f sunsynk-multi ``` -------------------------------- ### Add Custom Sensors to Configuration Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/mysensors.md YAML configuration snippets showing how to include custom sensors, either individually or as a group named 'mysensors'. ```yaml SENSORS: - my_custom_sensor_1 - my_custom_sensor_2 ``` ```yaml SENSORS: - mysensors ``` -------------------------------- ### System Settings Lovelace Card Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/examples/lovelace-settings.md This Lovelace YAML configures a vertical stack of horizontal stacks to display and edit system settings. It uses Mushroom entity cards and gauge cards for various parameters. Ensure you have the Mushroom cards installed via HACS. ```yaml type: vertical-stack cards: - type: horizontal-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog1_time fill_container: true secondary_info: none primary_info: state icon: mdi:numeric-1 - type: vertical-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog1_charge name: ' ' fill_container: false icon_type: none - type: custom:mushroom-entity-card entity: number.ss_prog1_power name: ' ' icon_type: none - type: gauge entity: number.ss_prog1_capacity name: ' ' needle: false - type: horizontal-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog2_time fill_container: true secondary_info: none primary_info: state icon: mdi:numeric-2 - type: vertical-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog2_charge name: ' ' fill_container: false icon_type: none - type: custom:mushroom-entity-card entity: number.ss_prog2_power name: ' ' icon_type: none - type: gauge entity: number.ss_prog2_capacity needle: false name: ' ' - type: horizontal-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog3_time fill_container: true secondary_info: none primary_info: state icon: mdi:numeric-3 - type: vertical-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog3_charge name: ' ' fill_container: false icon_type: none - type: custom:mushroom-entity-card entity: number.ss_prog3_power name: ' ' icon_type: none - type: gauge entity: number.ss_prog3_capacity needle: false name: ' ' - type: horizontal-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog4_time fill_container: true secondary_info: none primary_info: state icon: mdi:numeric-4 - type: vertical-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog4_charge name: ' ' fill_container: false icon_type: none - type: custom:mushroom-entity-card entity: number.ss_prog4_power name: ' ' icon_type: none - type: gauge entity: number.ss_prog4_capacity needle: false name: ' ' - type: horizontal-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog5_time fill_container: true secondary_info: none primary_info: state icon: mdi:numeric-5 - type: vertical-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog5_charge name: ' ' fill_container: false icon_type: none - type: custom:mushroom-entity-card entity: number.ss_prog5_power name: ' ' icon_type: none - type: gauge entity: number.ss_prog5_capacity needle: false name: ' ' - type: horizontal-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog6_time fill_container: true secondary_info: none primary_info: state icon: mdi:numeric-6 - type: vertical-stack cards: - type: custom:mushroom-entity-card entity: select.ss_prog6_charge name: ' ' fill_container: false icon_type: none - type: custom:mushroom-entity-card entity: number.ss_prog6_power name: ' ' icon_type: none - type: gauge entity: number.ss_prog6_capacity needle: false name: ' ' - type: entity entity: select.ss_load_limit ``` -------------------------------- ### Define Custom Sunsynk Sensors in Python Source: https://context7.com/kellerza/sunsynk/llms.txt Extend Sunsynk add-ons by creating a `mysensors.py` file in `/share/hass-addon-sunsynk/` to define custom sensors. This includes simple sensors, math-based sensors, read-write sensors, and custom sensor classes. ```python # /share/hass-addon-sunsynk/mysensors.py from sunsynk import AMPS, WATT, VOLT, SensorDefinitions, Sensor from sunsynk.rwsensors import NumberRWSensor from sunsynk.sensors import MathSensor, TempSensor from sunsynk.helpers import unpack_value, RegType, ValType from dataclasses import dataclass SENSORS = SensorDefinitions() # Simple read-only sensor SENSORS += Sensor(305, "AUX load power", WATT, -1) # Selling load: inverter output minus CT power SENSORS += MathSensor((175, 172), "Selling load power direct", WATT, factors=(1, 1)) # Custom read-write sensor for battery float voltage SENSORS += NumberRWSensor(143, "Battery float voltage", VOLT, factor=0.01, min=48.0, max=58.4) # Fully custom sensor class overriding reg_to_value @dataclass(slots=True, eq=False) class RatioSensor(Sensor): """Divides two registers.""" def reg_to_value(self, regs: RegType) -> ValType: val1 = unpack_value((regs[0],), signed=True) val2 = unpack_value((regs[1],), signed=True) if val2 == 0: return None return round(val1 / val2, 3) SENSORS += RatioSensor((175, 178), "Inverter-to-load ratio", "") ``` -------------------------------- ### Run Sunsynk Multi with Docker CLI (amd64/aarch64/armv6/armv7) Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Launches the Sunsynk Multi container using the Docker CLI. This command mounts the local options.yaml file and sets the container to restart automatically. ```bash docker run -d --name sunsynk-multi \ --restart unless-stopped \ -v ${PWD}/options.yaml:/data/options.yaml \ ghcr.io/kellerza/hass-addon-sunsynk-multi:stable ``` -------------------------------- ### Recommended Solarman Schedule Overrides Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/schedules.md Use these schedule overrides for the Solarman driver to ensure optimal performance and prevent dongle overload. Adjust READ_EVERY to be at least 15 seconds. ```yaml SCHEDULES: - KEY: W READ_EVERY: 15 REPORT_EVERY: 60 CHANGE_BY: 80 - KEY: RW READ_EVERY: 15 REPORT_EVERY: 60 CHANGE_ANY: true - KEY: any_unit READ_EVERY: 30 REPORT_EVERY: 60 CHANGE_BY: 80 ``` -------------------------------- ### PyModbus Driver Connection Options Source: https://context7.com/kellerza/sunsynk/llms.txt Demonstrates various connection methods for the `PySunsynk` driver, including serial RS485, Modbus TCP, RTU-over-TCP, and RTU-over-UDP. Also shows how to read raw holding registers and write to a single register. ```python from sunsynk.pysunsynk import PySunsynk # Serial RS485 connection inv_serial = PySunsynk(port="/dev/ttyUSB0", server_id=1) # Modbus TCP gateway (e.g., mbusd) inv_tcp = PySunsynk(port="tcp://192.168.1.100:502", server_id=1) # RTU-over-TCP (for gateways that don't do Modbus TCP translation) inv_rtu_tcp = PySunsynk(port="serial-tcp://192.168.1.100:8899", server_id=1) # RTU-over-UDP inv_rtu_udp = PySunsynk(port="serial-udp://192.168.1.100:8899", server_id=1) async def read_raw_registers(): await inv_tcp.connect() # Read 10 holding registers starting at address 150 regs = await inv_tcp.read_holding_registers(start=150, length=10) print(regs) # e.g. (2304, 0, 1450, 2100, 0, 0, 0, 0, 0, 0) # Write a single register value success = await inv_tcp.write_register(address=103, value=100) print(f"Write {'succeeded' if success else 'failed'}") ``` -------------------------------- ### Configure Mbusd Docker Compose Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Instructions for configuring the `docker-compose.yaml` file for the mbusd service. This includes setting environment variables and mounting the correct host serial port. ```yaml # Edit docker-compose.yaml changing the values under environment to match your configuration, leaving the device set to /dev/ttyUSB0 as we mount the correct port to this location in the next step. # Under volumes change /dev/ttyRS485 to the RS485 port of your host computer. ``` -------------------------------- ### Build Mbusd Docker Image Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Builds the mbusd Docker image using a specified base image. Replace `` with the appropriate image for your architecture. ```bash BUILD_FROM= docker compose build mbusd ``` -------------------------------- ### Include Custom Sensors Group Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/definitions.md Use the 'mysensors' group to add all your custom sensors defined elsewhere. Refer to the 'Custom Sensors' documentation for more details. ```yaml SENSORS: - mysensors ``` -------------------------------- ### View Mbusd Container Logs Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Displays the logs of the mbusd Docker container. ```bash docker compose logs -f mbusd ``` -------------------------------- ### Add Individual Devices to Energy Tracking Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/energy-management.md Configure these sensors to add individual devices, such as total load energy and active energy, to Home Assistant's energy tracking. ```yaml SENSORS: - total_load_energy - total_active_energy ``` -------------------------------- ### Enable Energy Management Sensor Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/energy-management.md Include this sensor in your addon configuration to enable basic energy management features. ```yaml SENSORS: - energy_management ``` -------------------------------- ### Configure Custom Sensors in Add-on YAML Source: https://context7.com/kellerza/sunsynk/llms.txt Specify custom sensors in the add-on YAML configuration. You can load all custom sensors from a file (e.g., `mysensors`) or individual sensors by their ID (e.g., `aux_load_power`). ```yaml SENSORS: - mysensors # load all custom sensors - aux_load_power # or load individual sensors by ID SENSOR_DEFINITIONS: single-phase ``` -------------------------------- ### Convert Sunsynk Inverter Time Formats Source: https://context7.com/kellerza/sunsynk/llms.txt Utilize the `SSTime` helper class to convert between the inverter's packed register time format (hours×100 + minutes) and human-readable `HH:MM` strings, or from total minutes. ```python from sunsynk.helpers import SSTime # From string to register t = SSTime(strv="22:30") print(t.reg_value) # 2230 (22*100 + 30) print(t.minutes) # 1350 (22*60 + 30) # From register value to string t2 = SSTime(regv=630) print(t2.str_value) # "6:30" print(t2.minutes) # 390 # From minutes t3 = SSTime(minutes=90) print(t3.str_value) # "1:30" print(t3.reg_value) # 130 (1*100 + 30) ``` -------------------------------- ### Docker Compose Service for Sunsynk Multi (amd64/aarch64/armv6/armv7) Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Defines the Sunsynk Multi service for Docker Compose, specifying the image and volume for options.yaml. This configuration is suitable for standard PC architectures. ```yaml services: sunsynk-multi: restart: unless-stopped image: ghcr.io/kellerza/hass-addon-sunsynk-multi:stable volumes: - ${PWD}/options.yaml:/data/options.yaml ``` -------------------------------- ### Include Settings Sensors Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/definitions.md Add the 'settings' group to include sensors used for changing the System Operating Mode. These can be configured under SENSORS or SENSORS_FIRST_INVERTER. ```yaml SENSORS_FIRST_INVERTER: - settings ``` -------------------------------- ### Displaying Sunsynk Sensor Values Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/examples/templates.md Use these templates to display detailed sensor information from your Sunsynk system within Home Assistant. Access these in the Developer Tools -> Templates tab. ```yaml Essentials: {{ states("sensor.ss_essential_power") }} W Non-Essentials: {{ states("sensor.ss_non_essential_power") }} W Grid CT: {{ states("sensor.ss_grid_ct_power") }} W Battery: {{ states("sensor.ss_battery_power") }} W {{ states("sensor.ss_battery_voltage") }} V {{ states("sensor.ss_battery_current") }} Amps {{ states("sensor.ss_battery_temperature") }} °C Grid Power: {{ states("sensor.ss_grid_power") }} W {{ states("sensor.ss_grid_frequency") }} Hz {{ states("sensor.ss_grid_voltage") }} V {{ states("sensor.ss_grid_current") }} Amp CT {{ states("sensor.ss_grid_ct_power") }} W Inverter {{ states("sensor.ss_inverter_power") }} W {{ states("sensor.ss_inverter_frequency") }} Hz Load {{ states("sensor.ss_essential_power") }} W {{ states("sensor.ss_grid_frequency") }} Hz {{ states("sensor.ss_grid_voltage") }} V {{ states("sensor.ss_grid_current") }} Amp PV1 {{ states("sensor.ss_pv1_power") }} W {{ states("sensor.ss_pv1_voltage") }} V {{ states("sensor.ss_pv1_current") }} A ``` -------------------------------- ### Docker Compose Service for Sunsynk Multi with Environment Variables Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/guide/standalone-deployment.md Configures the Sunsynk Multi service in Docker Compose to use environment variables for MQTT settings. The `S6_KEEP_ENV: 1` setting ensures environment variables are preserved. ```yaml services: sunsynk-multi: restart: unless-stopped image: ghcr.io/kellerza/hass-addon-sunsynk-multi:stable volumes: - ${PWD}/options.yaml:/data/options.yaml environment: MQTT_HOST: mqtt MQTT_PORT: 1883 MQTT_USERNAME: ${MQTT_USER} MQTT_PASSWORD: ${MQTT_PASSWORD} S6_KEEP_ENV: 1 ``` -------------------------------- ### Default Sensor Schedules Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/reference/schedules.md Displays the default read and report intervals for various sensor keys. These defaults apply when no specific schedule is configured. ```text +-----------+-----+------+--------+-----------+----------+------------+ | Key | src | Read | Report | Change by | Change % | Change any | +-----------+-----+------+--------+-----------+----------+------------+ | date_time | | 60 | 60 | | | True | | rw | | 5 | 300 | | | True | | w | | 5 | 60 | 80 | | | | kwh | | 300 | 300 | | | | | any_unit | | 15 | 300 | | | True | | no_unit | | 15 | 300 | | | True | +-----------+-----+------+--------+-----------+----------+------------+ ``` -------------------------------- ### Load and Override Sunsynk Sensor Definitions Source: https://context7.com/kellerza/sunsynk/llms.txt Load predefined inverter models using `import_defs` and dynamically adjust sensor attributes at runtime with `override`. Supports adding custom sensors. ```python from sunsynk.sensors import SensorDefinitions from sunsynk.definitions import import_defs, ALL_DEFS # Load a predefined model sensors = import_defs("single-phase") print(list(sensors.all.keys())[:5]) # ["device_type", "protocol", "serial", "battery_temperature", "battery_voltage"] # Override sensor attributes at runtime (e.g. for non-standard inverter configurations) sensors.override({ "battery_max_charge_current.max": 200, "prog4_power.max": 4990, "serial.trace": 1, }) # List all available definition sets print(ALL_DEFS) # ["single-phase", "single-phase-16kw", "three-phase", "three-phase-hv"] # Dynamically add custom sensors to an existing definition set from sunsynk.sensors import Sensor from sunsynk import WATT sensors += Sensor(178, "My extra load", WATT, -1) print(sensors.all["my_extra_load"].name) # My extra load ``` -------------------------------- ### Detect Load Shedding using Grid Frequency Source: https://github.com/kellerza/sunsynk/blob/main/www/docs/examples/a-mode.md This configuration creates a binary sensor to detect load shedding based on grid frequency dropping below 40 Hz. It also sets up an alert to notify users of power failures and their duration. ```yaml template: binary_sensor: - name: Load shedding state: "{{ states('sensor.ss_grid_frequency') | default (50) | int(0) < 40 }}" alert: load_shed: name: "Load shedding" message: "The power is off for - {{ relative_time(states.binary_sensor.load_shedding.last_changed) }}" done_message: "The power is back on" entity_id: binary_sensor.load_shedding repeat: - 2 - 30 - 60 - 120 can_acknowledge: true # Optional, default is true skip_first: true # Optional, false is the default notifiers: - mobile_app_johann_iphone ``` -------------------------------- ### Main AppArmor Profile for Sunsynk Addon Source: https://github.com/kellerza/sunsynk/blob/main/hass-addon-sunsynk-multi/apparmor.txt This is the main AppArmor profile for the Sunsynk addon. It includes global tunables and base abstractions, defines capabilities, and specifies access rules for S6-Overlay, Bashio, addon data, and the main program execution. ```apparmor #include profile ADDON_SLUG flags=(attach_disconnected,mediate_deleted) { #include # Capabilities file, signal (send) set=(kill,term,int,hup,cont), network, # S6-Overlay /init ix, /bin/** ix, /usr/bin/** ix, /run/{s6,s6-rc*,service}/** ix, /package/** ix, /command/** ix, /etc/services.d/** rwix, /etc/cont-init.d/** rwix, /etc/cont-finish.d/** rwix, /run/{,**} rwk, /dev/tty rw, # Bashio /usr/lib/bashio/** ix, /tmp/** rwk, # Access to options.json and other files within your addon /data/** rw, # Start new profile for service /usr/bin/myprogram cx -> myprogram, profile myprogram flags=(attach_disconnected,mediate_deleted) { #include # Receive signals from S6-Overlay signal (receive) peer=*_ADDON_SLUG, # Access to options.json and other files within your addon /data/** rw, # Access to mapped volumes specified in config.json /share/** rw, # Access required for service functionality # /usr/bin/myprogram r, /bin/bash rix, /bin/echo ix, /etc/passwd r, /dev/tty rw, } } ```