Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Salda Smarty XV/XP Ventilation Unit #21491

Merged
merged 6 commits into from Jun 6, 2019
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -537,6 +537,7 @@ omit =
homeassistant/components/slack/notify.py
homeassistant/components/sma/sensor.py
homeassistant/components/smappee/*
homeassistant/components/smarty/*
homeassistant/components/smtp/notify.py
homeassistant/components/snapcast/media_player.py
homeassistant/components/snmp/device_tracker.py
@@ -188,6 +188,7 @@ homeassistant/components/shodan/* @fabaff
homeassistant/components/simplisafe/* @bachya
homeassistant/components/sma/* @kellerza
homeassistant/components/smartthings/* @andrewsayre
homeassistant/components/smarty/* @z0mbieprocess
homeassistant/components/smtp/* @fabaff
homeassistant/components/sonos/* @amelchio
homeassistant/components/spaceapi/* @fabaff
@@ -0,0 +1,72 @@
"""Support to control a Salda Smarty XP/XV ventilation unit."""

from datetime import timedelta

import ipaddress
import logging
import voluptuous as vol
This conversation was marked as resolved by z0mbieprocess

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Mar 16, 2019

Member

Add a blank line between standard library and 3rd party imports.


from homeassistant.const import (CONF_NAME, CONF_HOST)
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import dispatcher_send
from homeassistant.helpers.event import track_time_interval

REQUIREMENTS = ['pysmarty==0.8']

This comment has been minimized.

Copy link
@balloob

balloob Jun 6, 2019

Member

This is no longer needed with a manifest.

DOMAIN = 'smarty'
This conversation was marked as resolved by z0mbieprocess

This comment has been minimized.

Copy link
@andrewsayre

andrewsayre Mar 16, 2019

Member

Move this constant up under requirements so it's easier to findthe HASS specific ones in a single grouping.

DATA_SMARTY = 'smarty'
SMARTY_NAME = 'Smarty'

_LOGGER = logging.getLogger(__name__)

CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema({
vol.Required(CONF_HOST): vol.All(ipaddress.ip_address, cv.string),
vol.Optional(CONF_NAME, default=SMARTY_NAME): cv.string
}),
},
extra=vol.ALLOW_EXTRA)

RPM = 'rpm'
SIGNAL_UPDATE_SMARTY = 'smarty_update'


def setup(hass, config):
"""Set up the smarty environment."""
from pysmarty import (Smarty)
conf = config[DOMAIN]

host = conf[CONF_HOST]
name = conf[CONF_NAME]

_LOGGER.debug("Name: %s, host: %s", name, host)

smarty = Smarty(host=host)

hass.data[DOMAIN] = {
'api': smarty,
'name': name
}

# Initial update
smarty.update()

# Load platforms
discovery.load_platform(hass, 'fan', DOMAIN, {}, config)
discovery.load_platform(hass, 'sensor', DOMAIN, {}, config)
discovery.load_platform(hass, 'binary_sensor', DOMAIN, {}, config)

def poll_device_update(event_time):
"""Update Smarty device."""
_LOGGER.debug("Updating Smarty device...")
if smarty.update():
_LOGGER.debug("Update success...")
dispatcher_send(hass, SIGNAL_UPDATE_SMARTY)
else:
_LOGGER.debug("Update failed...")

track_time_interval(hass, poll_device_update,
timedelta(seconds=30))

return True
@@ -0,0 +1,112 @@
"""Support for Salda Smarty XP/XV Ventilation Unit Binary Sensors."""

import logging

from homeassistant.core import callback
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import (DOMAIN, SIGNAL_UPDATE_SMARTY)

DEPENDENCIES = ['smarty']

_LOGGER = logging.getLogger(__name__)


async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Set up the Smarty Binary Sensor Platform."""
smarty = hass.data[DOMAIN]['api']
name = hass.data[DOMAIN]['name']

sensors = [AlarmSensor(name, smarty),
WarningSensor(name, smarty),
BoostSensor(name, smarty)]

async_add_entities(sensors, True)


class SmartyBinarySensor(BinarySensorDevice):
"""Representation of a Smarty Binary Sensor."""

def __init__(self, name, device_class, smarty):
"""Initialize the entity."""
self._name = name
self._state = None
self._sensor_type = device_class
self._smarty = smarty

@property
def device_class(self):
"""Return the class of the sensor."""
return self._sensor_type
This conversation was marked as resolved by z0mbieprocess

This comment has been minimized.

Copy link
@MartinHjelmare

MartinHjelmare Mar 23, 2019

Member

This doesn't seem to return anything but None.


@property
def should_poll(self) -> bool:
"""Do not poll."""
return False

@property
def name(self):
"""Return the name of the sensor."""
return self._name

@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state

async def async_added_to_hass(self):
"""Call to update."""
async_dispatcher_connect(self.hass,
SIGNAL_UPDATE_SMARTY,
self._update_callback)

@callback
def _update_callback(self):
"""Call update method."""
self.async_schedule_update_ha_state(True)


class BoostSensor(SmartyBinarySensor):
"""Boost State Binary Sensor."""

def __init__(self, name, smarty):
"""Alarm Sensor Init."""
super().__init__(name='{} Boost State'.format(name),
device_class=None,
smarty=smarty)

def update(self) -> None:
"""Update state."""
_LOGGER.debug('Updating sensor %s', self._name)
self._state = self._smarty.boost


class AlarmSensor(SmartyBinarySensor):
"""Alarm Binary Sensor."""

def __init__(self, name, smarty):
"""Alarm Sensor Init."""
super().__init__(name='{} Alarm'.format(name),
device_class='problem',
smarty=smarty)

def update(self) -> None:
"""Update state."""
_LOGGER.debug('Updating sensor %s', self._name)
self._state = self._smarty.alarm


class WarningSensor(SmartyBinarySensor):
"""Warning Sensor."""

def __init__(self, name, smarty):
"""Warning Sensor Init."""
super().__init__(name='{} Warning'.format(name),
device_class='problem',
smarty=smarty)

def update(self) -> None:
"""Update state."""
_LOGGER.debug('Updating sensor %s', self._name)
self._state = self._smarty.warning
@@ -0,0 +1,123 @@
"""Platform to control a Salda Smarty XP/XV ventilation unit."""

import logging

from homeassistant.core import callback
from homeassistant.components.fan import (
SPEED_HIGH, SPEED_LOW, SPEED_MEDIUM, SPEED_OFF, SUPPORT_SET_SPEED,
FanEntity)
from homeassistant.helpers.dispatcher import async_dispatcher_connect

from . import (DOMAIN, SIGNAL_UPDATE_SMARTY)

DEPENDENCIES = ['smarty']

This comment has been minimized.

Copy link
@balloob

balloob Jun 6, 2019

Member

This can be removed as it's in manifest.json


_LOGGER = logging.getLogger(__name__)

SPEED_LIST = [SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]

SPEED_MAPPING = {
1: SPEED_LOW,
2: SPEED_MEDIUM,
3: SPEED_HIGH
}
SPEED_TO_MODE = {v: k for k, v in SPEED_MAPPING.items()}


async def async_setup_platform(hass, config,
async_add_entities, discovery_info=None):
"""Set up the Smarty Fan Platform."""
smarty = hass.data[DOMAIN]['api']
name = hass.data[DOMAIN]['name']

async_add_entities([SmartyFan(name, smarty)], True)


class SmartyFan(FanEntity):
"""Representation of a Smarty Fan."""

def __init__(self, name, smarty):
"""Initialize the entity."""
self._name = name
self._speed = SPEED_OFF
self._state = None
self._smarty = smarty

@property
def should_poll(self):
"""Do not poll."""
return False

@property
def name(self):
"""Return the name of the fan."""
return self._name

@property
def icon(self):
"""Return the icon to use in the frontend."""
return 'mdi:air-conditioner'

@property
def supported_features(self):
"""Return the list of supported features."""
return SUPPORT_SET_SPEED

@property
def speed_list(self):
"""List of available fan modes."""
return SPEED_LIST

@property
def is_on(self):
"""Return state of the fan."""
return self._state

@property
def speed(self) -> str:
"""Return speed of the fan."""
return self._speed

def turn_on(self, speed=None, **kwargs):
"""Turn on the fan."""
_LOGGER.debug('Turning on fan. Speed is %s', speed)
if speed is None:
if self._smarty.turn_on(SPEED_TO_MODE.get(self._speed)):
self._state = True
self._speed = SPEED_MEDIUM
else:
if self._smarty.set_fan_speed(SPEED_TO_MODE.get(speed)):
self._speed = speed
self._state = True

self.schedule_update_ha_state()

def turn_off(self, **kwargs):
"""Turn off the fan."""
_LOGGER.debug('Turning off fan')
if self._smarty.turn_off():
self._state = False

self.schedule_update_ha_state()

async def async_added_to_hass(self):
"""Call to update fan."""
async_dispatcher_connect(self.hass,
SIGNAL_UPDATE_SMARTY,
self._update_callback)

@callback
def _update_callback(self):
"""Call update method."""
self.async_schedule_update_ha_state(True)

def update(self):
"""Update state."""
_LOGGER.debug('Updating state')
result = self._smarty.fan_speed
if result:
self._speed = SPEED_MAPPING[result]
_LOGGER.debug('Speed is %s, Mode is %s', self._speed, result)
self._state = True
else:
self._state = False
@@ -0,0 +1,13 @@
{
"domain": "smarty",
"name": "smarty",
"documentation": "https://www.home-assistant.io/components/smarty",
"requirements": [
"pysmarty==0.8"
],
"dependencies": [],
"codeowners": [
"@z0mbieprocess"
]
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.