Skip to content

Commit a63414a

Browse files
committed
Storage Mode entity - initial version
1 parent bbdab7a commit a63414a

File tree

3 files changed

+128
-0
lines changed

3 files changed

+128
-0
lines changed

custom_components/solis_cloud_control/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from homeassistant.core import HomeAssistant, ServiceCall, ServiceResponse, SupportsResponse
33
from homeassistant.exceptions import HomeAssistantError
44
from homeassistant.helpers import aiohttp_client
5+
from homeassistant.helpers.discovery import async_load_platform
56

67
from .api import SolisCloudControlApiClient, SolisCloudControlApiError
78
from .const import (
@@ -55,6 +56,16 @@ async def async_setup(hass: HomeAssistant, config: dict) -> bool:
5556

5657
client = SolisCloudControlApiClient(api_key, api_token, inverter_sn, session)
5758

59+
hass.async_create_task(
60+
async_load_platform(
61+
hass,
62+
"select",
63+
DOMAIN,
64+
{"client": client, "inverter_sn": inverter_sn},
65+
config,
66+
)
67+
)
68+
5869
async def async_service_read(call: ServiceCall) -> ServiceResponse:
5970
cid = call.data.get("cid")
6071
try:
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
from homeassistant.components.select import SelectEntity
2+
from homeassistant.core import HomeAssistant
3+
from homeassistant.helpers.entity import DeviceInfo
4+
5+
from .api import SolisCloudControlApiClient
6+
from .const import (
7+
DOMAIN,
8+
LOGGER,
9+
STORAGE_MODE_BIT_BACKUP_MODE,
10+
STORAGE_MODE_BIT_FEED_IN_PRIORITY,
11+
STORAGE_MODE_BIT_GRID_CHARGING,
12+
STORAGE_MODE_BIT_SELF_USE,
13+
STORAGE_MODE_CID,
14+
)
15+
16+
17+
class StorageModeEntity(SelectEntity):
18+
def __init__(self, hass: HomeAssistant, client: SolisCloudControlApiClient, serial_number: str) -> None:
19+
self._hass = hass
20+
self._client = client
21+
self._attr_name = "Storage Mode"
22+
self._attr_unique_id = f"{serial_number}_storage_mode"
23+
self.entity_id = f"select.solis_storage_mode_{serial_number.lower()}"
24+
self._attr_options = ["Self Use", "Feed In Priority"]
25+
self._attr_current_option = "Self Use"
26+
self._battery_reserve = "ON"
27+
self._allow_grid_charging = "OFF"
28+
self._attr_available = True
29+
self._attr_icon = "mdi:battery-charging"
30+
31+
self._attr_device_info = DeviceInfo(
32+
identifiers={(DOMAIN, serial_number)},
33+
name=f"Solis Inverter {serial_number}",
34+
manufacturer="Solis",
35+
model="Inverter",
36+
)
37+
38+
@property
39+
def extra_state_attributes(self) -> dict[str, str]:
40+
return {
41+
"battery_reserve": self._battery_reserve,
42+
"allow_grid_charging": self._allow_grid_charging,
43+
}
44+
45+
async def async_update(self) -> None:
46+
try:
47+
result = await self._client.read(STORAGE_MODE_CID)
48+
value_int = int(result)
49+
50+
if value_int & (1 << STORAGE_MODE_BIT_SELF_USE):
51+
self._attr_current_option = "Self Use"
52+
elif value_int & (1 << STORAGE_MODE_BIT_FEED_IN_PRIORITY):
53+
self._attr_current_option = "Feed In Priority"
54+
55+
self._battery_reserve = "ON" if value_int & (1 << STORAGE_MODE_BIT_BACKUP_MODE) else "OFF"
56+
self._allow_grid_charging = "ON" if value_int & (1 << STORAGE_MODE_BIT_GRID_CHARGING) else "OFF"
57+
58+
self._attr_available = True
59+
self.async_write_ha_state()
60+
except Exception as err:
61+
LOGGER.error("Failed to update storage mode: %s", err)
62+
self._attr_available = False
63+
self.async_write_ha_state()
64+
65+
async def async_select_option(self, option: str) -> None:
66+
value_int = 0
67+
68+
if option == "Self Use":
69+
value_int |= 1 << STORAGE_MODE_BIT_SELF_USE
70+
elif option == "Feed In Priority":
71+
value_int |= 1 << STORAGE_MODE_BIT_FEED_IN_PRIORITY
72+
73+
if self._battery_reserve == "ON":
74+
value_int |= 1 << STORAGE_MODE_BIT_BACKUP_MODE
75+
76+
if self._allow_grid_charging == "ON":
77+
value_int |= 1 << STORAGE_MODE_BIT_GRID_CHARGING
78+
79+
value = str(value_int)
80+
81+
await self._client.control(STORAGE_MODE_CID, value)
82+
self._attr_current_option = option
83+
self.async_write_ha_state()
84+
85+
async def async_set_battery_reserve(self, state: str) -> None:
86+
self._battery_reserve = state
87+
await self.async_select_option(self._attr_current_option)
88+
89+
async def async_set_allow_grid_charging(self, state: str) -> None:
90+
self._allow_grid_charging = state
91+
await self.async_select_option(self._attr_current_option)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from datetime import timedelta
2+
3+
from homeassistant.core import HomeAssistant
4+
from homeassistant.helpers.entity_platform import AddEntitiesCallback
5+
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
6+
7+
from .entity import StorageModeEntity
8+
9+
SCAN_INTERVAL = timedelta(minutes=5)
10+
11+
12+
async def async_setup_platform(
13+
hass: HomeAssistant,
14+
config: ConfigType,
15+
async_add_entities: AddEntitiesCallback,
16+
discovery_info: DiscoveryInfoType | None = None,
17+
) -> None:
18+
"""Set up the Solis Cloud Control select platform."""
19+
if discovery_info is None:
20+
return
21+
22+
client = discovery_info["client"]
23+
inverter_sn = discovery_info["inverter_sn"]
24+
25+
entities = [StorageModeEntity(hass, client, inverter_sn)]
26+
async_add_entities(entities, True)

0 commit comments

Comments
 (0)