switch.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. """Switch platform for Solar of Things integration."""
  2. from __future__ import annotations
  3. import logging
  4. from typing import Any
  5. from homeassistant.components.switch import SwitchEntity, SwitchDeviceClass
  6. from homeassistant.config_entries import ConfigEntry
  7. from homeassistant.core import HomeAssistant
  8. from homeassistant.helpers.entity_platform import AddEntitiesCallback
  9. from homeassistant.helpers.update_coordinator import CoordinatorEntity
  10. from .const import DOMAIN
  11. _LOGGER = logging.getLogger(__name__)
  12. async def async_setup_entry(
  13. hass: HomeAssistant,
  14. entry: ConfigEntry,
  15. async_add_entities: AddEntitiesCallback,
  16. ) -> None:
  17. """Set up Solar of Things switch entities based on a config entry."""
  18. coordinator = hass.data[DOMAIN][entry.entry_id]["coordinator"]
  19. api = hass.data[DOMAIN][entry.entry_id]["api"]
  20. entities = [
  21. SolarOfThingsGridChargingSwitch(
  22. coordinator=coordinator,
  23. entry=entry,
  24. api=api,
  25. ),
  26. SolarOfThingsGridFeedInSwitch(
  27. coordinator=coordinator,
  28. entry=entry,
  29. api=api,
  30. ),
  31. SolarOfThingsBackupModeSwitch(
  32. coordinator=coordinator,
  33. entry=entry,
  34. api=api,
  35. ),
  36. ]
  37. async_add_entities(entities)
  38. class SolarOfThingsGridChargingSwitch(CoordinatorEntity, SwitchEntity):
  39. """Switch entity for grid charging control."""
  40. def __init__(
  41. self,
  42. coordinator,
  43. entry: ConfigEntry,
  44. api,
  45. ) -> None:
  46. """Initialize the switch entity."""
  47. super().__init__(coordinator)
  48. self._entry = entry
  49. self._api = api
  50. self._attr_name = f"{entry.data.get('station_id', entry.data.get('device_id'))} Grid Charging"
  51. self._attr_unique_id = f"{entry.entry_id}_grid_charging"
  52. self._attr_device_class = SwitchDeviceClass.SWITCH
  53. self._attr_icon = "mdi:transmission-tower"
  54. @property
  55. def device_info(self):
  56. """Return device information."""
  57. return {
  58. "identifiers": {(DOMAIN, self._entry.entry_id)},
  59. "name": f"Solar Station {self._entry.data.get('station_id', self._entry.data.get('device_id'))}",
  60. "manufacturer": "Siseli",
  61. "model": "Solar Inverter",
  62. }
  63. @property
  64. def is_on(self) -> bool | None:
  65. """Return true if the switch is on."""
  66. if self.coordinator.data and "settings" in self.coordinator.data:
  67. return self.coordinator.data["settings"].get("gridChargingEnabled", False)
  68. return None
  69. async def async_turn_on(self, **kwargs: Any) -> None:
  70. """Turn the switch on."""
  71. try:
  72. await self.hass.async_add_executor_job(
  73. self._api.set_grid_charging,
  74. True
  75. )
  76. # Request immediate coordinator update
  77. await self.coordinator.async_request_refresh()
  78. except Exception as err:
  79. _LOGGER.error("Error turning on grid charging: %s", err)
  80. raise
  81. async def async_turn_off(self, **kwargs: Any) -> None:
  82. """Turn the switch off."""
  83. try:
  84. await self.hass.async_add_executor_job(
  85. self._api.set_grid_charging,
  86. False
  87. )
  88. # Request immediate coordinator update
  89. await self.coordinator.async_request_refresh()
  90. except Exception as err:
  91. _LOGGER.error("Error turning off grid charging: %s", err)
  92. raise
  93. class SolarOfThingsGridFeedInSwitch(CoordinatorEntity, SwitchEntity):
  94. """Switch entity for grid feed-in control."""
  95. def __init__(
  96. self,
  97. coordinator,
  98. entry: ConfigEntry,
  99. api,
  100. ) -> None:
  101. """Initialize the switch entity."""
  102. super().__init__(coordinator)
  103. self._entry = entry
  104. self._api = api
  105. self._attr_name = f"{entry.data.get('station_id', entry.data.get('device_id'))} Grid Feed-In"
  106. self._attr_unique_id = f"{entry.entry_id}_grid_feed_in"
  107. self._attr_device_class = SwitchDeviceClass.SWITCH
  108. self._attr_icon = "mdi:transmission-tower-export"
  109. @property
  110. def device_info(self):
  111. """Return device information."""
  112. return {
  113. "identifiers": {(DOMAIN, self._entry.entry_id)},
  114. "name": f"Solar Station {self._entry.data.get('station_id', self._entry.data.get('device_id'))}",
  115. "manufacturer": "Siseli",
  116. "model": "Solar Inverter",
  117. }
  118. @property
  119. def is_on(self) -> bool | None:
  120. """Return true if the switch is on."""
  121. if self.coordinator.data and "settings" in self.coordinator.data:
  122. return self.coordinator.data["settings"].get("gridFeedInEnabled", False)
  123. return None
  124. async def async_turn_on(self, **kwargs: Any) -> None:
  125. """Turn the switch on."""
  126. try:
  127. await self.hass.async_add_executor_job(
  128. self._api.set_grid_feed_in,
  129. True
  130. )
  131. # Request immediate coordinator update
  132. await self.coordinator.async_request_refresh()
  133. except Exception as err:
  134. _LOGGER.error("Error turning on grid feed-in: %s", err)
  135. raise
  136. async def async_turn_off(self, **kwargs: Any) -> None:
  137. """Turn the switch off."""
  138. try:
  139. await self.hass.async_add_executor_job(
  140. self._api.set_grid_feed_in,
  141. False
  142. )
  143. # Request immediate coordinator update
  144. await self.coordinator.async_request_refresh()
  145. except Exception as err:
  146. _LOGGER.error("Error turning off grid feed-in: %s", err)
  147. raise
  148. class SolarOfThingsBackupModeSwitch(CoordinatorEntity, SwitchEntity):
  149. """Switch entity for backup mode control."""
  150. def __init__(
  151. self,
  152. coordinator,
  153. entry: ConfigEntry,
  154. api,
  155. ) -> None:
  156. """Initialize the switch entity."""
  157. super().__init__(coordinator)
  158. self._entry = entry
  159. self._api = api
  160. self._attr_name = f"{entry.data.get('station_id', entry.data.get('device_id'))} Backup Mode"
  161. self._attr_unique_id = f"{entry.entry_id}_backup_mode"
  162. self._attr_device_class = SwitchDeviceClass.SWITCH
  163. self._attr_icon = "mdi:battery-lock"
  164. @property
  165. def device_info(self):
  166. """Return device information."""
  167. return {
  168. "identifiers": {(DOMAIN, self._entry.entry_id)},
  169. "name": f"Solar Station {self._entry.data.get('station_id', self._entry.data.get('device_id'))}",
  170. "manufacturer": "Siseli",
  171. "model": "Solar Inverter",
  172. }
  173. @property
  174. def is_on(self) -> bool | None:
  175. """Return true if the switch is on."""
  176. if self.coordinator.data and "settings" in self.coordinator.data:
  177. return self.coordinator.data["settings"].get("backupModeEnabled", False)
  178. return None
  179. async def async_turn_on(self, **kwargs: Any) -> None:
  180. """Turn the switch on."""
  181. try:
  182. await self.hass.async_add_executor_job(
  183. self._api.set_backup_mode,
  184. True
  185. )
  186. # Request immediate coordinator update
  187. await self.coordinator.async_request_refresh()
  188. except Exception as err:
  189. _LOGGER.error("Error turning on backup mode: %s", err)
  190. raise
  191. async def async_turn_off(self, **kwargs: Any) -> None:
  192. """Turn the switch off."""
  193. try:
  194. await self.hass.async_add_executor_job(
  195. self._api.set_backup_mode,
  196. False
  197. )
  198. # Request immediate coordinator update
  199. await self.coordinator.async_request_refresh()
  200. except Exception as err:
  201. _LOGGER.error("Error turning off backup mode: %s", err)
  202. raise