Add ADS component (#10142)
* add ads hub, light and switch
* add binary sensor prototype
* switch: use adsvar for connection
* fix some issues with binary sensor
* fix binary sensor
* fix all platforms
* use latest pyads
* fixed error with multiple binary sensors
* add sensor
* add ads sensor
* clean up after shutdown
* ads component with platforms switch, binary_sensor, light, sensor
add locking
poll sensors at startup
update state of ads switch and light
update ads requirements
remove update() from constructors on ads platforms
omit ads coverage
ads catch read error when polling
* add ads service
* add default settings for use_notify and poll_interval
* fix too long line
* Fix style issues
* no pydocstyle errors
* Send and receive native brightness data to ADS device to prevent issues with math.floor reducing brightness -1 at every switch
* Enable non dimmable lights
* remove setting of self._state in switch
* remove polling
* Revert "remove polling"
This reverts commit 7da420f823
.
* add service schema, add links to documentation
* fix naming, cleanup
* re-remove polling
* use async_added_to_hass for setup of callbacks
* fix comment.
* add callbacks for changed values
* use async_add_job for creating device notifications
* set should_poll to False for all platforms
* change should_poll to property
* add service description to services.yaml
* add for brigthness not being None
* put ads component in package
* Remove whitespace
* omit ads package
pull/10967/head
parent
38a1f06d14
commit
53d9fd18b7
homeassistant/components
|
@ -11,6 +11,9 @@ omit =
|
|||
homeassistant/components/abode.py
|
||||
homeassistant/components/*/abode.py
|
||||
|
||||
homeassistant/components/ads/__init__.py
|
||||
homeassistant/components/*/ads.py
|
||||
|
||||
homeassistant/components/alarmdecoder.py
|
||||
homeassistant/components/*/alarmdecoder.py
|
||||
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
"""
|
||||
ADS Component.
|
||||
|
||||
For more details about this component, please refer to the documentation.
|
||||
https://home-assistant.io/components/ads/
|
||||
|
||||
"""
|
||||
import os
|
||||
import threading
|
||||
import struct
|
||||
import logging
|
||||
import ctypes
|
||||
from collections import namedtuple
|
||||
import voluptuous as vol
|
||||
from homeassistant.const import CONF_DEVICE, CONF_PORT, CONF_IP_ADDRESS, \
|
||||
EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
REQUIREMENTS = ['pyads==2.2.6']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DATA_ADS = 'data_ads'
|
||||
|
||||
# Supported Types
|
||||
ADSTYPE_INT = 'int'
|
||||
ADSTYPE_UINT = 'uint'
|
||||
ADSTYPE_BYTE = 'byte'
|
||||
ADSTYPE_BOOL = 'bool'
|
||||
|
||||
DOMAIN = 'ads'
|
||||
|
||||
# config variable names
|
||||
CONF_ADS_VAR = 'adsvar'
|
||||
CONF_ADS_VAR_BRIGHTNESS = 'adsvar_brightness'
|
||||
CONF_ADS_TYPE = 'adstype'
|
||||
CONF_ADS_FACTOR = 'factor'
|
||||
CONF_ADS_VALUE = 'value'
|
||||
|
||||
SERVICE_WRITE_DATA_BY_NAME = 'write_data_by_name'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(CONF_DEVICE): cv.string,
|
||||
vol.Required(CONF_PORT): cv.port,
|
||||
vol.Optional(CONF_IP_ADDRESS): cv.string,
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
SCHEMA_SERVICE_WRITE_DATA_BY_NAME = vol.Schema({
|
||||
vol.Required(CONF_ADS_VAR): cv.string,
|
||||
vol.Required(CONF_ADS_TYPE): vol.In([ADSTYPE_INT, ADSTYPE_UINT,
|
||||
ADSTYPE_BYTE]),
|
||||
vol.Required(CONF_ADS_VALUE): cv.match_all
|
||||
})
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up the ADS component."""
|
||||
import pyads
|
||||
conf = config[DOMAIN]
|
||||
|
||||
# get ads connection parameters from config
|
||||
net_id = conf.get(CONF_DEVICE)
|
||||
ip_address = conf.get(CONF_IP_ADDRESS)
|
||||
port = conf.get(CONF_PORT)
|
||||
|
||||
# create a new ads connection
|
||||
client = pyads.Connection(net_id, port, ip_address)
|
||||
|
||||
# add some constants to AdsHub
|
||||
AdsHub.ADS_TYPEMAP = {
|
||||
ADSTYPE_BOOL: pyads.PLCTYPE_BOOL,
|
||||
ADSTYPE_BYTE: pyads.PLCTYPE_BYTE,
|
||||
ADSTYPE_INT: pyads.PLCTYPE_INT,
|
||||
ADSTYPE_UINT: pyads.PLCTYPE_UINT,
|
||||
}
|
||||
|
||||
AdsHub.PLCTYPE_BOOL = pyads.PLCTYPE_BOOL
|
||||
AdsHub.PLCTYPE_BYTE = pyads.PLCTYPE_BYTE
|
||||
AdsHub.PLCTYPE_INT = pyads.PLCTYPE_INT
|
||||
AdsHub.PLCTYPE_UINT = pyads.PLCTYPE_UINT
|
||||
AdsHub.ADSError = pyads.ADSError
|
||||
|
||||
# connect to ads client and try to connect
|
||||
try:
|
||||
ads = AdsHub(client)
|
||||
except pyads.pyads.ADSError:
|
||||
_LOGGER.error(
|
||||
'Could not connect to ADS host (netid=%s, port=%s)', net_id, port
|
||||
)
|
||||
return False
|
||||
|
||||
# add ads hub to hass data collection, listen to shutdown
|
||||
hass.data[DATA_ADS] = ads
|
||||
hass.bus.listen(EVENT_HOMEASSISTANT_STOP, ads.shutdown)
|
||||
|
||||
def handle_write_data_by_name(call):
|
||||
"""Write a value to the connected ADS device."""
|
||||
ads_var = call.data.get(CONF_ADS_VAR)
|
||||
ads_type = call.data.get(CONF_ADS_TYPE)
|
||||
value = call.data.get(CONF_ADS_VALUE)
|
||||
|
||||
try:
|
||||
ads.write_by_name(ads_var, value, ads.ADS_TYPEMAP[ads_type])
|
||||
except pyads.ADSError as err:
|
||||
_LOGGER.error(err)
|
||||
|
||||
# load descriptions from services.yaml
|
||||
descriptions = load_yaml_config_file(
|
||||
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
||||
|
||||
hass.services.register(
|
||||
DOMAIN, SERVICE_WRITE_DATA_BY_NAME, handle_write_data_by_name,
|
||||
descriptions[SERVICE_WRITE_DATA_BY_NAME],
|
||||
schema=SCHEMA_SERVICE_WRITE_DATA_BY_NAME
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# tuple to hold data needed for notification
|
||||
NotificationItem = namedtuple(
|
||||
'NotificationItem', 'hnotify huser name plc_datatype callback'
|
||||
)
|
||||
|
||||
|
||||
class AdsHub:
|
||||
"""Representation of a PyADS connection."""
|
||||
|
||||
def __init__(self, ads_client):
|
||||
"""Initialize the ADS Hub."""
|
||||
self._client = ads_client
|
||||
self._client.open()
|
||||
|
||||
# all ADS devices are registered here
|
||||
self._devices = []
|
||||
self._notification_items = {}
|
||||
self._lock = threading.Lock()
|
||||
|
||||
def shutdown(self, *args, **kwargs):
|
||||
"""Shutdown ADS connection."""
|
||||
_LOGGER.debug('Shutting down ADS')
|
||||
for notification_item in self._notification_items.values():
|
||||
self._client.del_device_notification(
|
||||
notification_item.hnotify,
|
||||
notification_item.huser
|
||||
)
|
||||
_LOGGER.debug(
|
||||
'Deleting device notification %d, %d',
|
||||
notification_item.hnotify, notification_item.huser
|
||||
)
|
||||
self._client.close()
|
||||
|
||||
def register_device(self, device):
|
||||
"""Register a new device."""
|
||||
self._devices.append(device)
|
||||
|
||||
def write_by_name(self, name, value, plc_datatype):
|
||||
"""Write a value to the device."""
|
||||
with self._lock:
|
||||
return self._client.write_by_name(name, value, plc_datatype)
|
||||
|
||||
def read_by_name(self, name, plc_datatype):
|
||||
"""Read a value from the device."""
|
||||
with self._lock:
|
||||
return self._client.read_by_name(name, plc_datatype)
|
||||
|
||||
def add_device_notification(self, name, plc_datatype, callback):
|
||||
"""Add a notification to the ADS devices."""
|
||||
from pyads import NotificationAttrib
|
||||
attr = NotificationAttrib(ctypes.sizeof(plc_datatype))
|
||||
|
||||
with self._lock:
|
||||
hnotify, huser = self._client.add_device_notification(
|
||||
name, attr, self._device_notification_callback
|
||||
)
|
||||
hnotify = int(hnotify)
|
||||
|
||||
_LOGGER.debug(
|
||||
'Added Device Notification %d for variable %s', hnotify, name
|
||||
)
|
||||
|
||||
self._notification_items[hnotify] = NotificationItem(
|
||||
hnotify, huser, name, plc_datatype, callback
|
||||
)
|
||||
|
||||
def _device_notification_callback(self, addr, notification, huser):
|
||||
"""Handle device notifications."""
|
||||
contents = notification.contents
|
||||
|
||||
hnotify = int(contents.hNotification)
|
||||
_LOGGER.debug('Received Notification %d', hnotify)
|
||||
data = contents.data
|
||||
|
||||
try:
|
||||
notification_item = self._notification_items[hnotify]
|
||||
except KeyError:
|
||||
_LOGGER.debug('Unknown Device Notification handle: %d', hnotify)
|
||||
return
|
||||
|
||||
# parse data to desired datatype
|
||||
if notification_item.plc_datatype == self.PLCTYPE_BOOL:
|
||||
value = bool(struct.unpack('<?', bytearray(data)[:1])[0])
|
||||
elif notification_item.plc_datatype == self.PLCTYPE_INT:
|
||||
value = struct.unpack('<h', bytearray(data)[:2])[0]
|
||||
elif notification_item.plc_datatype == self.PLCTYPE_BYTE:
|
||||
value = struct.unpack('<B', bytearray(data)[:1])[0]
|
||||
elif notification_item.plc_datatype == self.PLCTYPE_UINT:
|
||||
value = struct.unpack('<H', bytearray(data)[:2])[0]
|
||||
else:
|
||||
value = bytearray(data)
|
||||
_LOGGER.warning('No callback available for this datatype.')
|
||||
|
||||
# execute callback
|
||||
notification_item.callback(notification_item.name, value)
|
|
@ -0,0 +1,15 @@
|
|||
# Describes the format for available ADS services
|
||||
|
||||
write_data_by_name:
|
||||
description: Write a value to the connected ADS device.
|
||||
|
||||
fields:
|
||||
adsvar:
|
||||
description: The name of the variable to write to.
|
||||
example: '.global_var'
|
||||
adstype:
|
||||
description: The data type of the variable to write to.
|
||||
example: 'int'
|
||||
value:
|
||||
description: The value to write to the variable.
|
||||
example: 1
|
|
@ -0,0 +1,87 @@
|
|||
"""
|
||||
Support for ADS binary sensors.
|
||||
|
||||
For more details about this platform, please refer to the documentation.
|
||||
https://home-assistant.io/components/binary_sensor.ads/
|
||||
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
import voluptuous as vol
|
||||
from homeassistant.components.binary_sensor import BinarySensorDevice, \
|
||||
PLATFORM_SCHEMA, DEVICE_CLASSES_SCHEMA
|
||||
from homeassistant.components.ads import DATA_ADS, CONF_ADS_VAR
|
||||
from homeassistant.const import CONF_NAME, CONF_DEVICE_CLASS
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEPENDENCIES = ['ads']
|
||||
DEFAULT_NAME = 'ADS binary sensor'
|
||||
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_ADS_VAR): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up the Binary Sensor platform for ADS."""
|
||||
ads_hub = hass.data.get(DATA_ADS)
|
||||
|
||||
ads_var = config.get(CONF_ADS_VAR)
|
||||
name = config.get(CONF_NAME)
|
||||
device_class = config.get(CONF_DEVICE_CLASS)
|
||||
|
||||
ads_sensor = AdsBinarySensor(ads_hub, name, ads_var, device_class)
|
||||
add_devices([ads_sensor])
|
||||
|
||||
|
||||
class AdsBinarySensor(BinarySensorDevice):
|
||||
"""Representation of ADS binary sensors."""
|
||||
|
||||
def __init__(self, ads_hub, name, ads_var, device_class):
|
||||
"""Initialize AdsBinarySensor entity."""
|
||||
self._name = name
|
||||
self._state = False
|
||||
self._device_class = device_class or 'moving'
|
||||
self._ads_hub = ads_hub
|
||||
self.ads_var = ads_var
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_added_to_hass(self):
|
||||
"""Register device notification."""
|
||||
def update(name, value):
|
||||
"""Handle device notifications."""
|
||||
_LOGGER.debug('Variable %s changed its value to %d',
|
||||
name, value)
|
||||
self._state = value
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
self.hass.async_add_job(
|
||||
self._ads_hub.add_device_notification,
|
||||
self.ads_var, self._ads_hub.PLCTYPE_BOOL, update
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the default name of the binary sensor."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the device class."""
|
||||
return self._device_class
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return if the binary sensor is on."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Return False because entity pushes its state to HA."""
|
||||
return False
|
|
@ -0,0 +1,117 @@
|
|||
"""
|
||||
Support for ADS light sources.
|
||||
|
||||
For more details about this platform, please refer to the documentation.
|
||||
https://home-assistant.io/components/light.ads/
|
||||
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
import voluptuous as vol
|
||||
from homeassistant.components.light import Light, ATTR_BRIGHTNESS, \
|
||||
SUPPORT_BRIGHTNESS, PLATFORM_SCHEMA
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.components.ads import DATA_ADS, CONF_ADS_VAR, \
|
||||
CONF_ADS_VAR_BRIGHTNESS
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
DEPENDENCIES = ['ads']
|
||||
DEFAULT_NAME = 'ADS Light'
|
||||
CONF_ADSVAR_BRIGHTNESS = 'adsvar_brightness'
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_ADS_VAR): cv.string,
|
||||
vol.Optional(CONF_ADS_VAR_BRIGHTNESS): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up the light platform for ADS."""
|
||||
ads_hub = hass.data.get(DATA_ADS)
|
||||
|
||||
ads_var_enable = config.get(CONF_ADS_VAR)
|
||||
ads_var_brightness = config.get(CONF_ADS_VAR_BRIGHTNESS)
|
||||
name = config.get(CONF_NAME)
|
||||
|
||||
add_devices([AdsLight(ads_hub, ads_var_enable, ads_var_brightness,
|
||||
name)], True)
|
||||
|
||||
|
||||
class AdsLight(Light):
|
||||
"""Representation of ADS light."""
|
||||
|
||||
def __init__(self, ads_hub, ads_var_enable, ads_var_brightness, name):
|
||||
"""Initialize AdsLight entity."""
|
||||
self._ads_hub = ads_hub
|
||||
self._on_state = False
|
||||
self._brightness = None
|
||||
self._name = name
|
||||
self.ads_var_enable = ads_var_enable
|
||||
self.ads_var_brightness = ads_var_brightness
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_added_to_hass(self):
|
||||
"""Register device notification."""
|
||||
def update_on_state(name, value):
|
||||
"""Handle device notifications for state."""
|
||||
_LOGGER.debug('Variable %s changed its value to %d', name, value)
|
||||
self._on_state = value
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def update_brightness(name, value):
|
||||
"""Handle device notification for brightness."""
|
||||
_LOGGER.debug('Variable %s changed its value to %d', name, value)
|
||||
self._brightness = value
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
self.hass.async_add_job(
|
||||
self._ads_hub.add_device_notification,
|
||||
self.ads_var_enable, self._ads_hub.PLCTYPE_BOOL, update_on_state
|
||||
)
|
||||
self.hass.async_add_job(
|
||||
self._ads_hub.add_device_notification,
|
||||
self.ads_var_brightness, self._ads_hub.PLCTYPE_INT,
|
||||
update_brightness
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device if any."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Return the brightness of the light (0..255)."""
|
||||
return self._brightness
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return if light is on."""
|
||||
return self._on_state
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Return False because entity pushes its state to HA."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
if self.ads_var_brightness is not None:
|
||||
return SUPPORT_BRIGHTNESS
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the light on or set a specific dimmer value."""
|
||||
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
||||
self._ads_hub.write_by_name(self.ads_var_enable, True,
|
||||
self._ads_hub.PLCTYPE_BOOL)
|
||||
|
||||
if self.ads_var_brightness is not None and brightness is not None:
|
||||
self._ads_hub.write_by_name(self.ads_var_brightness, brightness,
|
||||
self._ads_hub.PLCTYPE_UINT)
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the light off."""
|
||||
self._ads_hub.write_by_name(self.ads_var_enable, False,
|
||||
self._ads_hub.PLCTYPE_BOOL)
|
|
@ -0,0 +1,103 @@
|
|||
"""
|
||||
Support for ADS sensors.
|
||||
|
||||
For more details about this platform, please refer to the documentation.
|
||||
https://home-assistant.io/components/sensor.ads/
|
||||
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
import voluptuous as vol
|
||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT
|
||||
from homeassistant.helpers.entity import Entity
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.components import ads
|
||||
from homeassistant.components.ads import CONF_ADS_VAR, CONF_ADS_TYPE, \
|
||||
CONF_ADS_FACTOR
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_NAME = 'ADS sensor'
|
||||
DEPENDENCIES = ['ads']
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_ADS_VAR): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT, default=''): cv.string,
|
||||
vol.Optional(CONF_ADS_TYPE, default=ads.ADSTYPE_INT): vol.In(
|
||||
[ads.ADSTYPE_INT, ads.ADSTYPE_UINT, ads.ADSTYPE_BYTE]
|
||||
),
|
||||
vol.Optional(CONF_ADS_FACTOR): cv.positive_int,
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up an ADS sensor device."""
|
||||
ads_hub = hass.data.get(ads.DATA_ADS)
|
||||
|
||||
ads_var = config.get(CONF_ADS_VAR)
|
||||
ads_type = config.get(CONF_ADS_TYPE)
|
||||
name = config.get(CONF_NAME)
|
||||
unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
|
||||
factor = config.get(CONF_ADS_FACTOR)
|
||||
|
||||
entity = AdsSensor(ads_hub, ads_var, ads_type, name,
|
||||
unit_of_measurement, factor)
|
||||
|
||||
add_devices([entity])
|
||||
|
||||
|
||||
class AdsSensor(Entity):
|
||||
"""Representation of an ADS sensor entity."""
|
||||
|
||||
def __init__(self, ads_hub, ads_var, ads_type, name, unit_of_measurement,
|
||||
factor):
|
||||
"""Initialize AdsSensor entity."""
|
||||
self._ads_hub = ads_hub
|
||||
self._name = name
|
||||
self._value = None
|
||||
self._unit_of_measurement = unit_of_measurement
|
||||
self.ads_var = ads_var
|
||||
self.ads_type = ads_type
|
||||
self.factor = factor
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_added_to_hass(self):
|
||||
"""Register device notification."""
|
||||
def update(name, value):
|
||||
"""Handle device notifications."""
|
||||
_LOGGER.debug('Variable %s changed its value to %d', name, value)
|
||||
|
||||
# if factor is set use it otherwise not
|
||||
if self.factor is None:
|
||||
self._value = value
|
||||
else:
|
||||
self._value = value / self.factor
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
self.hass.async_add_job(
|
||||
self._ads_hub.add_device_notification,
|
||||
self.ads_var, self._ads_hub.ADS_TYPEMAP[self.ads_type], update
|
||||
)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the entity."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the device."""
|
||||
return self._value
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement."""
|
||||
return self._unit_of_measurement
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Return False because entity pushes its state to HA."""
|
||||
return False
|
|
@ -437,7 +437,7 @@ input_text:
|
|||
set_value:
|
||||
description: Set the value of an input text entity.
|
||||
fields:
|
||||
entity_id:
|
||||
entity_id:
|
||||
description: Entity id of the input text to set the new value.
|
||||
example: 'input_text.text1'
|
||||
value:
|
||||
|
@ -448,7 +448,7 @@ input_number:
|
|||
set_value:
|
||||
description: Set the value of an input number entity.
|
||||
fields:
|
||||
entity_id:
|
||||
entity_id:
|
||||
description: Entity id of the input number to set the new value.
|
||||
example: 'input_number.threshold'
|
||||
value:
|
||||
|
@ -457,13 +457,13 @@ input_number:
|
|||
increment:
|
||||
description: Increment the value of an input number entity by its stepping.
|
||||
fields:
|
||||
entity_id:
|
||||
entity_id:
|
||||
description: Entity id of the input number the should be incremented.
|
||||
example: 'input_number.threshold'
|
||||
decrement:
|
||||
description: Decrement the value of an input number entity by its stepping.
|
||||
fields:
|
||||
entity_id:
|
||||
entity_id:
|
||||
description: Entity id of the input number the should be decremented.
|
||||
example: 'input_number.threshold'
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
"""
|
||||
Support for ADS switch platform.
|
||||
|
||||
For more details about this platform, please refer to the documentation.
|
||||
https://home-assistant.io/components/switch.ads/
|
||||
|
||||
"""
|
||||
import asyncio
|
||||
import logging
|
||||
import voluptuous as vol
|
||||
from homeassistant.components.switch import PLATFORM_SCHEMA
|
||||
from homeassistant.const import CONF_NAME
|
||||
from homeassistant.components.ads import DATA_ADS, CONF_ADS_VAR
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
DEPENDENCIES = ['ads']
|
||||
DEFAULT_NAME = 'ADS Switch'
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_ADS_VAR): cv.string,
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Set up switch platform for ADS."""
|
||||
ads_hub = hass.data.get(DATA_ADS)
|
||||
|
||||
name = config.get(CONF_NAME)
|
||||
ads_var = config.get(CONF_ADS_VAR)
|
||||
|
||||
add_devices([AdsSwitch(ads_hub, name, ads_var)], True)
|
||||
|
||||
|
||||
class AdsSwitch(ToggleEntity):
|
||||
"""Representation of an Ads switch device."""
|
||||
|
||||
def __init__(self, ads_hub, name, ads_var):
|
||||
"""Initialize the AdsSwitch entity."""
|
||||
self._ads_hub = ads_hub
|
||||
self._on_state = False
|
||||
self._name = name
|
||||
self.ads_var = ads_var
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_added_to_hass(self):
|
||||
"""Register device notification."""
|
||||
def update(name, value):
|
||||
"""Handle device notification."""
|
||||
_LOGGER.debug('Variable %s changed its value to %d',
|
||||
name, value)
|
||||
self._on_state = value
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
self.hass.async_add_job(
|
||||
self._ads_hub.add_device_notification,
|
||||
self.ads_var, self._ads_hub.PLCTYPE_BOOL, update
|
||||
)
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return if the switch is turned on."""
|
||||
return self._on_state
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the entity."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
"""Return False because entity pushes its state to HA."""
|
||||
return False
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the switch on."""
|
||||
self._ads_hub.write_by_name(self.ads_var, True,
|
||||
self._ads_hub.PLCTYPE_BOOL)
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the switch off."""
|
||||
self._ads_hub.write_by_name(self.ads_var, False,
|
||||
self._ads_hub.PLCTYPE_BOOL)
|
|
@ -600,6 +600,9 @@ pyTibber==0.2.1
|
|||
# homeassistant.components.switch.dlink
|
||||
pyW215==0.6.0
|
||||
|
||||
# homeassistant.components.ads
|
||||
pyads==2.2.6
|
||||
|
||||
# homeassistant.components.sensor.airvisual
|
||||
pyairvisual==1.0.0
|
||||
|
||||
|
|
Loading…
Reference in New Issue