-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
5471aed
commit cc34305
Showing
11 changed files
with
656 additions
and
199 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,87 @@ | ||
"""The WEM Portal component.""" | ||
""" | ||
wemportal integration | ||
Author: erikkastelec | ||
https://github.com/erikkastelec/hass-WEM-Portal | ||
""" | ||
from datetime import timedelta | ||
|
||
import voluptuous as vol | ||
|
||
from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME | ||
from homeassistant.core import HomeAssistant, callback | ||
import homeassistant.helpers.config_validation as config_validation | ||
from homeassistant.helpers.typing import ConfigType | ||
|
||
from .const import CONF_LANGUAGE, CONF_MODE, CONF_SCAN_INTERVAL_API, DOMAIN, PLATFORMS | ||
from .coordinator import WemPortalDataUpdateCoordinator | ||
from .wemportalapi import WemPortalApi | ||
|
||
CONFIG_SCHEMA = vol.Schema( | ||
{ | ||
vol.Optional(DOMAIN, default=[]): vol.Schema( | ||
{ | ||
vol.Optional( | ||
CONF_SCAN_INTERVAL, default=timedelta(minutes=30) | ||
): config_validation.time_period, | ||
vol.Optional( | ||
CONF_SCAN_INTERVAL_API, default=timedelta(minutes=5) | ||
): config_validation.time_period, | ||
vol.Optional(CONF_LANGUAGE, default="en"): config_validation.string, | ||
vol.Optional(CONF_MODE, default="both"): config_validation.string, | ||
vol.Required(CONF_USERNAME): config_validation.string, | ||
vol.Required(CONF_PASSWORD): config_validation.string, | ||
} | ||
) | ||
}, | ||
extra=vol.ALLOW_EXTRA, | ||
) | ||
|
||
|
||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: | ||
"""Set up the wemportal component.""" | ||
# Set proper update_interval, based on selected mode | ||
if config[DOMAIN].get(CONF_MODE) == "web": | ||
update_interval = config[DOMAIN].get(CONF_SCAN_INTERVAL) | ||
|
||
elif config[DOMAIN].get(CONF_MODE) == "api": | ||
update_interval = config[DOMAIN].get(CONF_SCAN_INTERVAL_API) | ||
else: | ||
update_interval = min( | ||
config[DOMAIN].get(CONF_SCAN_INTERVAL), | ||
config[DOMAIN].get(CONF_SCAN_INTERVAL_API), | ||
) | ||
# Creatie API object | ||
api = WemPortalApi(config[DOMAIN]) | ||
# Create custom coordinator | ||
coordinator = WemPortalDataUpdateCoordinator(hass, api, update_interval) | ||
|
||
hass.data[DOMAIN] = { | ||
"api": api, | ||
"config": config[DOMAIN], | ||
"coordinator": coordinator, | ||
} | ||
|
||
await coordinator.async_config_entry_first_refresh() | ||
|
||
# Initialize platforms | ||
for platform in PLATFORMS: | ||
hass.helpers.discovery.load_platform(platform, DOMAIN, {}, config) | ||
return True | ||
|
||
# """Remove obsolete entities from entity registry.""" | ||
|
||
# if hap.home.currentAPVersion < "2.2.12": | ||
# return | ||
|
||
# entity_registry = er.async_get(hass) | ||
# er_entries = async_entries_for_config_entry(entity_registry, entry.entry_id) | ||
# for er_entry in er_entries: | ||
# if er_entry.unique_id.startswith("HomematicipAccesspointStatus"): | ||
# entity_registry.async_remove(er_entry.entity_id) | ||
# continue | ||
|
||
# for hapid in hap.home.accessPointUpdateStates: | ||
# if er_entry.unique_id == f"HomematicipBatterySensor_{hapid}": | ||
# entity_registry.async_remove(er_entry.entity_id) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
""" WemPortal integration coordinator """ | ||
from __future__ import annotations | ||
|
||
import async_timeout | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator | ||
|
||
from .const import _LOGGER, DEFAULT_TIMEOUT | ||
from .wemportalapi import WemPortalApi | ||
|
||
|
||
class WemPortalDataUpdateCoordinator(DataUpdateCoordinator): | ||
"""DataUpdateCoordinator for wemportal component""" | ||
|
||
def __init__(self, hass: HomeAssistant, api: WemPortalApi, update_interval): | ||
"""Initialize DataUpdateCoordinator for the wemportal component""" | ||
super().__init__( | ||
hass, | ||
_LOGGER, | ||
name="WemPortal update", | ||
update_interval=update_interval, | ||
) | ||
self.api = api | ||
self.has = hass | ||
|
||
async def _async_update_data(self): | ||
"""Fetch data from the wemportal api""" | ||
async with async_timeout.timeout(DEFAULT_TIMEOUT): | ||
return await self.hass.async_add_executor_job(self.api.fetch_data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
""" | ||
Number platform for wemportal component | ||
""" | ||
|
||
from homeassistant.components.number import NumberEntity | ||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
from homeassistant.helpers.update_coordinator import CoordinatorEntity | ||
|
||
from .const import _LOGGER, DOMAIN | ||
|
||
|
||
async def async_setup_platform( | ||
hass: HomeAssistant, | ||
config_entry: ConfigEntry, | ||
async_add_entities: AddEntitiesCallback, | ||
discovery_info=None, | ||
): | ||
"""Setup the Wem Portal sensors.""" | ||
|
||
coordinator = hass.data[DOMAIN]["coordinator"] | ||
|
||
entities: list[WemPortalNumber] = [] | ||
for unique_id, values in coordinator.data.items(): | ||
if values["platform"] == "number": | ||
_LOGGER.warning(unique_id) | ||
entities.append(WemPortalNumber(coordinator, unique_id, values)) | ||
|
||
async_add_entities(entities) | ||
|
||
|
||
class WemPortalNumber(CoordinatorEntity, NumberEntity): | ||
"""Representation of a WEM Portal number.""" | ||
|
||
def __init__(self, coordinator, _unique_id, entity_data): | ||
"""Initialize the sensor.""" | ||
super().__init__(coordinator) | ||
self._last_updated = None | ||
self._name = _unique_id | ||
self._parameter_id = entity_data["ParameterID"] | ||
self._unique_id = _unique_id | ||
self._icon = entity_data["icon"] | ||
self._unit = entity_data["unit"] | ||
self._state = self.state | ||
self._attr_min_value = entity_data["min_value"] | ||
self._attr_max_value = entity_data["max_value"] | ||
self._attr_step = entity_data["step"] | ||
self._module_index = entity_data["ModuleIndex"] | ||
self._module_type = entity_data["ModuleType"] | ||
|
||
async def async_set_value(self, value: float) -> None: | ||
"""Update the current value.""" | ||
await self.hass.async_add_executor_job( | ||
self.coordinator.api.change_value, | ||
self._parameter_id, | ||
self._module_index, | ||
self._module_type, | ||
value, | ||
) | ||
self._state = value | ||
self.coordinator.data[self._unique_id]["value"] = value | ||
self.async_write_ha_state() | ||
|
||
@property | ||
def should_poll(self): | ||
"""No need to poll. Coordinator notifies entity of updates.""" | ||
return False | ||
|
||
@property | ||
def available(self): | ||
"""Return if entity is available.""" | ||
return self.coordinator.last_update_success | ||
|
||
async def async_added_to_hass(self): | ||
"""When entity is added to hass.""" | ||
self.coordinator.async_add_listener(self.async_write_ha_state) | ||
|
||
async def async_will_remove_from_hass(self): | ||
"""When entity will be removed from hass.""" | ||
self.coordinator.async_remove_listener(self.async_write_ha_state) | ||
|
||
@property | ||
def name(self): | ||
"""Return the name of the sensor.""" | ||
return self._name | ||
|
||
@property | ||
def unique_id(self): | ||
"""Return the unique ID of the binary sensor.""" | ||
return self._unique_id | ||
|
||
@property | ||
def icon(self): | ||
"""Icon to use in the frontend, if any.""" | ||
return self._icon | ||
|
||
@property | ||
def state(self): | ||
"""Return the state of the sensor.""" | ||
try: | ||
state = self.coordinator.data[self._unique_id]["value"] | ||
if state: | ||
return state | ||
return 0 | ||
except KeyError: | ||
_LOGGER.error("Can't find %s", self._unique_id) | ||
_LOGGER.debug("Sensor data %s", self.coordinator.data) | ||
return None | ||
|
||
@property | ||
def unit_of_measurement(self): | ||
"""Return the unit of measurement of this entity, if any.""" | ||
return self._unit | ||
|
||
# @property | ||
# def state_class(self): | ||
# """Return the state class of this entity, if any.""" | ||
# if self._unit in ("°C", "kW", "W", "%"): | ||
# return STATE_CLASS_MEASUREMENT | ||
# elif self._unit in ("kWh", "Wh"): | ||
# return STATE_CLASS_TOTAL_INCREASING | ||
# else: | ||
# return None | ||
|
||
@property | ||
def extra_state_attributes(self): | ||
"""Return the state attributes of this device.""" | ||
attr = {} | ||
if self._last_updated is not None: | ||
attr["Last Updated"] = self._last_updated | ||
return attr | ||
|
||
async def async_update(self): | ||
"""Update Entity | ||
Only used by the generic entity update service.""" | ||
await self.coordinator.async_request_refresh() |
Oops, something went wrong.