core/homeassistant/components/supla/__init__.py

152 lines
4.4 KiB
Python
Raw Normal View History

"""Support for Supla devices."""
import logging
from typing import Optional
import voluptuous as vol
from homeassistant.const import CONF_ACCESS_TOKEN
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.discovery import load_platform
from homeassistant.helpers.entity import Entity
2019-07-31 19:25:30 +00:00
REQUIREMENTS = ["pysupla==0.0.3"]
_LOGGER = logging.getLogger(__name__)
2019-07-31 19:25:30 +00:00
DOMAIN = "supla"
2019-07-31 19:25:30 +00:00
CONF_SERVER = "server"
CONF_SERVERS = "servers"
2019-07-31 19:25:30 +00:00
SUPLA_FUNCTION_HA_CMP_MAP = {"CONTROLLINGTHEROLLERSHUTTER": "cover"}
SUPLA_CHANNELS = "supla_channels"
SUPLA_SERVERS = "supla_servers"
2019-07-31 19:25:30 +00:00
SERVER_CONFIG = vol.Schema(
{vol.Required(CONF_SERVER): cv.string, vol.Required(CONF_ACCESS_TOKEN): cv.string}
)
2019-07-31 19:25:30 +00:00
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{vol.Required(CONF_SERVERS): vol.All(cv.ensure_list, [SERVER_CONFIG])}
)
},
extra=vol.ALLOW_EXTRA,
)
def setup(hass, base_config):
"""Set up the Supla component."""
from pysupla import SuplaAPI
server_confs = base_config[DOMAIN][CONF_SERVERS]
hass.data[SUPLA_SERVERS] = {}
hass.data[SUPLA_CHANNELS] = {}
for server_conf in server_confs:
server_address = server_conf[CONF_SERVER]
2019-07-31 19:25:30 +00:00
server = SuplaAPI(server_address, server_conf[CONF_ACCESS_TOKEN])
# Test connection
try:
srv_info = server.get_server_info()
2019-07-31 19:25:30 +00:00
if srv_info.get("authenticated"):
hass.data[SUPLA_SERVERS][server_conf[CONF_SERVER]] = server
else:
_LOGGER.error(
2019-07-31 19:25:30 +00:00
"Server: %s not configured. API call returned: %s",
server_address,
2019-07-31 19:25:30 +00:00
srv_info,
)
return False
except IOError:
_LOGGER.exception(
2019-07-31 19:25:30 +00:00
"Server: %s not configured. Error on Supla API access: ", server_address
)
return False
discover_devices(hass, base_config)
return True
def discover_devices(hass, hass_config):
"""
Run periodically to discover new devices.
Currently it's only run at startup.
"""
component_configs = {}
for server_name, server in hass.data[SUPLA_SERVERS].items():
2019-07-31 19:25:30 +00:00
for channel in server.get_channels(include=["iodevice"]):
channel_function = channel["function"]["name"]
component_name = SUPLA_FUNCTION_HA_CMP_MAP.get(channel_function)
if component_name is None:
_LOGGER.warning(
2019-07-31 19:25:30 +00:00
"Unsupported function: %s, channel id: %s",
channel_function,
channel["id"],
)
continue
2019-07-31 19:25:30 +00:00
channel["server_name"] = server_name
component_configs.setdefault(component_name, []).append(channel)
# Load discovered devices
for component_name, channel in component_configs.items():
2019-07-31 19:25:30 +00:00
load_platform(hass, component_name, "supla", channel, hass_config)
class SuplaChannel(Entity):
"""Base class of a Supla Channel (an equivalent of HA's Entity)."""
def __init__(self, channel_data):
"""Channel data -- raw channel information from PySupla."""
2019-07-31 19:25:30 +00:00
self.server_name = channel_data["server_name"]
self.channel_data = channel_data
@property
def server(self):
"""Return PySupla's server component associated with entity."""
return self.hass.data[SUPLA_SERVERS][self.server_name]
@property
def unique_id(self) -> str:
"""Return a unique ID."""
2019-07-31 19:25:30 +00:00
return "supla-{}-{}".format(
self.channel_data["iodevice"]["gUIDString"].lower(),
self.channel_data["channelNumber"],
)
@property
def name(self) -> Optional[str]:
"""Return the name of the device."""
2019-07-31 19:25:30 +00:00
return self.channel_data["caption"]
def action(self, action, **add_pars):
"""
Run server action.
Actions are currently hardcoded in components.
Supla's API enables autodiscovery
"""
_LOGGER.debug(
2019-07-31 19:25:30 +00:00
"Executing action %s on channel %d, params: %s",
action,
2019-07-31 19:25:30 +00:00
self.channel_data["id"],
add_pars,
)
2019-07-31 19:25:30 +00:00
self.server.execute_action(self.channel_data["id"], action, **add_pars)
def update(self):
"""Call to update state."""
self.channel_data = self.server.get_channel(
2019-07-31 19:25:30 +00:00
self.channel_data["id"], include=["connected", "state"]
)