diff --git a/custom_components/solarman/const.py b/custom_components/solarman/const.py index 3d44d82c..e7fb2bb0 100644 --- a/custom_components/solarman/const.py +++ b/custom_components/solarman/const.py @@ -1,7 +1,7 @@ from datetime import timedelta as td DOMAIN = "solarman" -PLATFORMS: list[str] = ["sensor", "switch"] +PLATFORMS: list[str] = ["sensor", "switch", "number"] IP_BROADCAST = "" IP_ANY = "0.0.0.0" diff --git a/custom_components/solarman/inverter_definitions/deye_sg01hp3.yaml b/custom_components/solarman/inverter_definitions/deye_sg01hp3.yaml index a7a97649..7182ef55 100644 --- a/custom_components/solarman/inverter_definitions/deye_sg01hp3.yaml +++ b/custom_components/solarman/inverter_definitions/deye_sg01hp3.yaml @@ -193,14 +193,16 @@ parameters: registers: [0x0067] icon: "mdi:battery" - - name: "Zero Export" - attribute: + - name: "Zero Export power" class: "power" state_class: "measurement" uom: "W" scale: 1 rule: 1 registers: [0x0068] + configurable: + min: 0 + max: 500 icon: "mdi:transmission-tower-import" - name: "Battery Equalization Cycle" @@ -1273,7 +1275,6 @@ parameters: rule: 4 registers: [0x0271, 0x02B2] icon: "mdi:transmission-tower" - attributes: ["Zero Export"] - group: Inverter items: diff --git a/custom_components/solarman/inverter_definitions/deye_sg04lp3.yaml b/custom_components/solarman/inverter_definitions/deye_sg04lp3.yaml index 82c889df..991d5c6f 100644 --- a/custom_components/solarman/inverter_definitions/deye_sg04lp3.yaml +++ b/custom_components/solarman/inverter_definitions/deye_sg04lp3.yaml @@ -199,13 +199,16 @@ parameters: registers: [0x0067] icon: "mdi:battery" - - name: "Zero Export Power" + - name: "Zero Export power" class: "power" state_class: "measurement" uom: "W" scale: 1 rule: 1 registers: [0x0068] + configurable: + min: 0 + max: 500 icon: "mdi:transmission-tower-import" - name: "Battery Equalization Cycle" diff --git a/custom_components/solarman/inverter_definitions/deye_sun-12k-sg04lp3.yaml b/custom_components/solarman/inverter_definitions/deye_sun-12k-sg04lp3.yaml index e541b7e0..20e1a1b8 100644 --- a/custom_components/solarman/inverter_definitions/deye_sun-12k-sg04lp3.yaml +++ b/custom_components/solarman/inverter_definitions/deye_sun-12k-sg04lp3.yaml @@ -201,14 +201,16 @@ parameters: registers: [0x0067] icon: "mdi:battery" - - name: "Zero Export" - attribute: + - name: "Zero Export power" class: "power" state_class: "measurement" uom: "W" scale: 1 rule: 1 registers: [0x0068] + configurable: + min: 0 + max: 500 icon: "mdi:transmission-tower-import" - name: "Battery Equalization Cycle" @@ -1290,7 +1292,6 @@ parameters: rule: 4 registers: [0x0271, 0x02B2] icon: "mdi:transmission-tower" - attributes: ["Zero Export"] # Grid - The inverted power is S16bit (low 16 bits) + S16bit (high 16 bits) - name: "Grid Power ∇" @@ -1304,7 +1305,6 @@ parameters: inverted: True registers: [0x0271, 0x02B2] icon: "mdi:transmission-tower" - attributes: ["Zero Export"] - group: Inverter items: diff --git a/custom_components/solarman/number.py b/custom_components/solarman/number.py new file mode 100644 index 00000000..2168ebdb --- /dev/null +++ b/custom_components/solarman/number.py @@ -0,0 +1,84 @@ +from __future__ import annotations + +import logging +import asyncio +import voluptuous as vol + +from functools import cached_property, partial + +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant, callback +from homeassistant.const import CONF_NAME, STATE_OFF, STATE_ON, EntityCategory +from homeassistant.components.number import NumberEntity, NumberDeviceClass, NumberEntityDescription +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import * +from .common import * +from .services import * +from .sensor import SolarmanSensor + +_LOGGER = logging.getLogger(__name__) + +_PLATFORM = get_current_file_name(__name__) + +def _create_sensor(coordinator, sensor): + try: + entity = SolarmanNumberEntity(coordinator, sensor) + + entity.update() + + return entity + except BaseException as e: + _LOGGER.error(f"Configuring {sensor} failed. [{format_exception(e)}]") + raise + +async def async_setup_entry(hass: HomeAssistant, config: ConfigEntry, async_add_entities: AddEntitiesCallback) -> bool: + _LOGGER.debug(f"async_setup_entry: {config.options}") + coordinator = hass.data[DOMAIN][config.entry_id] + + sensors = coordinator.inverter.get_sensors() + + # Add entities. + # + _LOGGER.debug(f"async_setup: async_add_entities") + + async_add_entities(_create_sensor(coordinator, sensor) for sensor in sensors if "configurable" in sensor) + #if ("class" in sensor and sensor["class"] == _PLATFORM) + return True + +async def async_unload_entry(hass: HomeAssistant, config: ConfigEntry) -> bool: + _LOGGER.debug(f"async_unload_entry: {config.options}") + return True + +class SolarmanNumberEntity(SolarmanSensor, NumberEntity): + def __init__(self, coordinator, sensor): + SolarmanSensor.__init__(self, coordinator, sensor, 0) + # Set The Category of the entity. + self._attr_entity_category = EntityCategory.CONFIG + + registers = sensor["registers"] + registers_length = len(registers) + if registers_length > 0: + self.register = sensor["registers"][0] + if registers_length > 1: + _LOGGER.warning(f"SolarmanNumberEntity.__init__: Contains more than 1 register!") + + configurable = sensor["configurable"] + if "min" in configurable: + self._attr_native_min_value = configurable["min"] + if "max" in configurable: + self._attr_native_max_value = configurable["max"] + + @property + def native_value(self) -> float: + """Return the state of the setting entity.""" + return self._attr_state + + async def async_set_native_value(self, value: float) -> None: + """Update the setting.""" + int_value = int(value) + await self.coordinator.inverter.service_write_multiple_holding_registers(self.register, [int_value,]) + self._attr_state = int_value + self.async_write_ha_state() + #await self.entity_description.update_fn(self.coordinator., int(value)) + #await self.coordinator.async_request_refresh() diff --git a/custom_components/solarman/sensor.py b/custom_components/solarman/sensor.py index 2753a33e..c0b642ae 100644 --- a/custom_components/solarman/sensor.py +++ b/custom_components/solarman/sensor.py @@ -59,7 +59,7 @@ async def async_setup_entry(hass: HomeAssistant, config: ConfigEntry, async_add_ # _LOGGER.debug(f"async_setup: async_add_entities") - async_add_entities(_create_sensor(coordinator, sensor, battery_nominal_voltage, battery_life_cycle_rating) for sensor in sensors if (not "class" in sensor or not sensor["class"] in PLATFORMS)) + async_add_entities(_create_sensor(coordinator, sensor, battery_nominal_voltage, battery_life_cycle_rating) for sensor in sensors if ((not "class" in sensor or not sensor["class"] in PLATFORMS) and not "configurable" in sensor)) return True async def async_unload_entry(hass: HomeAssistant, config: ConfigEntry) -> bool: diff --git a/custom_components/solarman/switch.py b/custom_components/solarman/switch.py index fcd1bfa7..b019ced7 100644 --- a/custom_components/solarman/switch.py +++ b/custom_components/solarman/switch.py @@ -6,25 +6,15 @@ from functools import cached_property, partial -from homeassistant.components.template.sensor import SensorTemplate -from homeassistant.components.template.sensor import TriggerSensorEntity -from homeassistant.components.switch import SwitchEntity, SwitchDeviceClass, SwitchEntityDescription -from homeassistant.helpers.template import Template - -from homeassistant.core import HomeAssistant, callback from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_NAME, EntityCategory, STATE_OFF, STATE_ON -from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo, format_mac -from homeassistant.helpers.entity import Entity, ToggleEntity +from homeassistant.core import HomeAssistant, callback +from homeassistant.const import CONF_NAME, STATE_OFF, STATE_ON, EntityCategory +from homeassistant.components.switch import SwitchEntity, SwitchDeviceClass, SwitchEntityDescription from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import * from .common import * from .services import * -from .api import Inverter -from .coordinator import InverterCoordinator -from .entity import SolarmanCoordinatorEntity, SolarmanBaseEntity, SolarmanEntity from .sensor import SolarmanSensor _LOGGER = logging.getLogger(__name__)