Upgrade insteonplm to 0.8.2 (required refactoring) (#12534)

* Merge from current dev

* Update for Sensor approach

* Update reference to state classes

* Reference stateKey correctly

* Reference stateKey

* Change deviceInfo to a dict

* Pass state to properties method

* Add state info to device_state_attributes

* Update entity name to include state name

* Update for on() off() vs light_on/off

* Flag newnames option

* Update configuration schema

* Update configuration schema

* Spell False correctly

* Rename state to statekey

* Rename statekey to stateKey

* Call new device with stateKey and newname

* Simplify use of newnames

* Add workdir to save devices

* Fix newnames config setup

* Propogate OnOffSensor to VariableSensor change

* Upgrade insteonplm version to 0.8.0

* Pass address rather than device object to platform

* Set inteon_plm data variable to PLM

* Consistant use of conn and plm

* Consistant use of conn and plm

* Proper reference to device and address

* Fixed platform setup issues

* Correct issue with missing _supported_features attr

* Properly reference self._state vs self.state

* Bump insteonplm version to 0.8.1

* Remove subplatform and map based on state name

* Correct refrence to State

* Correct reference to device.states

* Bump insteonplm to 0.8.2

* Fix format errors

* Fix format issues

* Fix trailing whitespace

* Correct format issues

* Fix format issues

* Fix format issues

* Fixed format issues

* Fixed format issues

* Move imports inside classes

* Simplify import of modules

* Correct reference to OnOffSwitch_OutletTop and bottom

* Remove unnessary references

* Fix format issues

* Code review adjustments

* Fix format issue

* Use new nameing format for groups that are not group 0x01

* Remove newname feature

* Fix binary_sensor type to default to None

* Fix device_class property to return the sensor type correctly.

* rename _device and _state to avoid conflicts with Entity

* Format long lines

* Pylint clean up

* Insteon_PLM

* lint cleanup

* Check device_override has address

* 3.4 lint clean up

* Changes per code review

* Change discovered from a list of dict to a dict

* Correct common_attributes usage

* Change discovered from a list of dict to a dict

* Add debugging message to confirm platform setup

* Debug messages

* Debug messages

* Debug async_added_to_hass

* Debug async_added_to_hass async_add_job

* Debug async_added_to_hass

* Debug devices not loading in hass

* Debug new entities not being added to hass

* Debug adding devices to hass

* Revert "3.4 lint clean up"

This reverts commit 0d8fb992b12e9eea86716753fd2f302b1addb458.

* 3.4 lint clean up

* Revert "Debug adding devices to hass"

This reverts commit ec306773d47401b100bcdaaf0af47c93699d78b4.

* Revert "Debug new entities not being added to hass"

This reverts commit 55fb724d06e7d1e249de46acb2de7eac2eb7d14d.

* Revert "Debug devices not loading in hass"

This reverts commit 07814b4f14cab85e67197812b055a2d71a954b1f.

* Revert "Debug async_added_to_hass"

This reverts commit 4963a255d86c1bf63ec6064b0d911893d310f13d.

* Revert "Debug async_added_to_hass async_add_job"

This reverts commit 22cadff91f524edf91605c4c1f9df0a3d125d1d9.

* Revert "Debug async_added_to_hass"

This reverts commit 12c5651fe497b439ba962473973232ae9745314d.

* Pylint clean up

* pylint cleanup

* Clean up naming

* Enhance config schema. Fix logging issue

* Reapply changes after squash
This commit is contained in:
Tom Harris 2018-02-25 14:13:39 -05:00 committed by Martin Hjelmare
parent e8173fbc16
commit 32166fd56a
7 changed files with 371 additions and 249 deletions

View File

@ -2,86 +2,56 @@
Support for INSTEON dimmers via PowerLinc Modem. Support for INSTEON dimmers via PowerLinc Modem.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/insteon_plm/ https://home-assistant.io/components/binary_sensor.insteon_plm/
""" """
import logging
import asyncio import asyncio
import logging
from homeassistant.core import callback
from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.loader import get_component from homeassistant.components.insteon_plm import InsteonPLMEntity
DEPENDENCIES = ['insteon_plm'] DEPENDENCIES = ['insteon_plm']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = {'openClosedSensor': 'opening',
'motionSensor': 'motion',
'doorSensor': 'door',
'leakSensor': 'moisture'}
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the INSTEON PLM device class for the hass platform.""" """Set up the INSTEON PLM device class for the hass platform."""
plm = hass.data['insteon_plm'] plm = hass.data['insteon_plm']
device_list = [] address = discovery_info['address']
for device in discovery_info: device = plm.devices[address]
name = device.get('address') state_key = discovery_info['state_key']
address = device.get('address_hex')
_LOGGER.info('Registered %s with binary_sensor platform.', name) _LOGGER.debug('Adding device %s entity %s to Binary Sensor platform',
device.address.hex, device.states[state_key].name)
device_list.append( new_entity = InsteonPLMBinarySensor(device, state_key)
InsteonPLMBinarySensorDevice(hass, plm, address, name)
)
async_add_devices(device_list) async_add_devices([new_entity])
class InsteonPLMBinarySensorDevice(BinarySensorDevice): class InsteonPLMBinarySensor(InsteonPLMEntity, BinarySensorDevice):
"""A Class for an Insteon device.""" """A Class for an Insteon device entity."""
def __init__(self, hass, plm, address, name): def __init__(self, device, state_key):
"""Initialize the binarysensor.""" """Initialize the INSTEON PLM binary sensor."""
self._hass = hass super().__init__(device, state_key)
self._plm = plm.protocol self._sensor_type = SENSOR_TYPES.get(self._insteon_device_state.name)
self._address = address
self._name = name
self._plm.add_update_callback(
self.async_binarysensor_update, {'address': self._address})
@property @property
def should_poll(self): def device_class(self):
"""No polling needed.""" """Return the class of this sensor."""
return False return self._sensor_type
@property
def address(self):
"""Return the address of the node."""
return self._address
@property
def name(self):
"""Return the name of the node."""
return self._name
@property @property
def is_on(self): def is_on(self):
"""Return the boolean response if the node is on.""" """Return the boolean response if the node is on."""
sensorstate = self._plm.get_device_attr(self._address, 'sensorstate') sensorstate = self._insteon_device_state.value
_LOGGER.info("Sensor state for %s is %s", self._address, sensorstate)
return bool(sensorstate) return bool(sensorstate)
@property
def device_state_attributes(self):
"""Provide attributes for display on device card."""
insteon_plm = get_component('insteon_plm')
return insteon_plm.common_attributes(self)
def get_attr(self, key):
"""Return specified attribute for this device."""
return self._plm.get_device_attr(self.address, key)
@callback
def async_binarysensor_update(self, message):
"""Receive notification from transport that new data exists."""
_LOGGER.info("Received update callback from PLM for %s", self._address)
self._hass.async_add_job(self.async_update_ha_state())

View File

@ -0,0 +1,96 @@
"""
Support for INSTEON fans via PowerLinc Modem.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/fan.insteon_plm/
"""
import asyncio
import logging
from homeassistant.components.fan import (SPEED_OFF,
SPEED_LOW,
SPEED_MEDIUM,
SPEED_HIGH,
FanEntity,
SUPPORT_SET_SPEED)
from homeassistant.const import STATE_OFF
from homeassistant.components.insteon_plm import InsteonPLMEntity
DEPENDENCIES = ['insteon_plm']
SPEED_TO_HEX = {SPEED_OFF: 0x00,
SPEED_LOW: 0x3f,
SPEED_MEDIUM: 0xbe,
SPEED_HIGH: 0xff}
FAN_SPEEDS = [STATE_OFF, SPEED_LOW, SPEED_MEDIUM, SPEED_HIGH]
_LOGGER = logging.getLogger(__name__)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the INSTEON PLM device class for the hass platform."""
plm = hass.data['insteon_plm']
address = discovery_info['address']
device = plm.devices[address]
state_key = discovery_info['state_key']
_LOGGER.debug('Adding device %s entity %s to Fan platform',
device.address.hex, device.states[state_key].name)
new_entity = InsteonPLMFan(device, state_key)
async_add_devices([new_entity])
class InsteonPLMFan(InsteonPLMEntity, FanEntity):
"""An INSTEON fan component."""
@property
def speed(self) -> str:
"""Return the current speed."""
return self._hex_to_speed(self._insteon_device_state.value)
@property
def speed_list(self) -> list:
"""Get the list of available speeds."""
return FAN_SPEEDS
@property
def supported_features(self) -> int:
"""Flag supported features."""
return SUPPORT_SET_SPEED
@asyncio.coroutine
def async_turn_on(self, speed: str = None, **kwargs) -> None:
"""Turn on the entity."""
if speed is None:
speed = SPEED_MEDIUM
yield from self.async_set_speed(speed)
@asyncio.coroutine
def async_turn_off(self, **kwargs) -> None:
"""Turn off the entity."""
yield from self.async_set_speed(SPEED_OFF)
@asyncio.coroutine
def async_set_speed(self, speed: str) -> None:
"""Set the speed of the fan."""
fan_speed = SPEED_TO_HEX[speed]
if fan_speed == 0x00:
self._insteon_device_state.off()
else:
self._insteon_device_state.set_level(fan_speed)
@staticmethod
def _hex_to_speed(speed: int):
hex_speed = SPEED_OFF
if speed > 0xfe:
hex_speed = SPEED_HIGH
elif speed > 0x7f:
hex_speed = SPEED_MEDIUM
elif speed > 0:
hex_speed = SPEED_LOW
return hex_speed

View File

@ -4,117 +4,211 @@ Support for INSTEON PowerLinc Modem.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/insteon_plm/ https://home-assistant.io/components/insteon_plm/
""" """
import logging
import asyncio import asyncio
import collections
import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.const import ( from homeassistant.const import (CONF_PORT, EVENT_HOMEASSISTANT_STOP,
CONF_PORT, EVENT_HOMEASSISTANT_STOP) CONF_PLATFORM)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['insteonplm==0.7.5'] REQUIREMENTS = ['insteonplm==0.8.2']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = 'insteon_plm' DOMAIN = 'insteon_plm'
CONF_OVERRIDE = 'device_override' CONF_OVERRIDE = 'device_override'
CONF_ADDRESS = 'address'
CONF_CAT = 'cat'
CONF_SUBCAT = 'subcat'
CONF_FIRMWARE = 'firmware'
CONF_PRODUCT_KEY = 'product_key'
CONF_DEVICE_OVERRIDE_SCHEMA = vol.All(
cv.deprecated(CONF_PLATFORM), vol.Schema({
vol.Required(CONF_ADDRESS): cv.string,
vol.Optional(CONF_CAT): cv.byte,
vol.Optional(CONF_SUBCAT): cv.byte,
vol.Optional(CONF_FIRMWARE): cv.byte,
vol.Optional(CONF_PRODUCT_KEY): cv.byte,
vol.Optional(CONF_PLATFORM): cv.string,
}))
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({ DOMAIN: vol.Schema({
vol.Required(CONF_PORT): cv.string, vol.Required(CONF_PORT): cv.string,
vol.Optional(CONF_OVERRIDE, default=[]): cv.ensure_list_csv, vol.Optional(CONF_OVERRIDE): vol.All(
}) cv.ensure_list_csv, [CONF_DEVICE_OVERRIDE_SCHEMA])
})
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
PLM_PLATFORMS = {
'binary_sensor': ['binary_sensor'],
'light': ['light'],
'switch': ['switch'],
}
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Set up the connection to the PLM.""" """Set up the connection to the PLM."""
import insteonplm import insteonplm
ipdb = IPDB()
conf = config[DOMAIN] conf = config[DOMAIN]
port = conf.get(CONF_PORT) port = conf.get(CONF_PORT)
overrides = conf.get(CONF_OVERRIDE) overrides = conf.get(CONF_OVERRIDE, [])
@callback @callback
def async_plm_new_device(device): def async_plm_new_device(device):
"""Detect device from transport to be delegated to platform.""" """Detect device from transport to be delegated to platform."""
name = device.get('address') for state_key in device.states:
address = device.get('address_hex') platform_info = ipdb[device.states[state_key]]
capabilities = device.get('capabilities', []) platform = platform_info.platform
if platform is not None:
_LOGGER.info("New INSTEON PLM device: %s (%s) %s",
device.address,
device.states[state_key].name,
platform)
_LOGGER.info("New INSTEON PLM device: %s (%s) %r", hass.async_add_job(
name, address, capabilities) discovery.async_load_platform(
hass, platform, DOMAIN,
loadlist = [] discovered={'address': device.address.hex,
for platform in PLM_PLATFORMS: 'state_key': state_key},
caplist = PLM_PLATFORMS.get(platform) hass_config=config))
for key in capabilities:
if key in caplist:
loadlist.append(platform)
loadlist = sorted(set(loadlist))
for loadplatform in loadlist:
hass.async_add_job(
discovery.async_load_platform(
hass, loadplatform, DOMAIN, discovered=[device],
hass_config=config))
_LOGGER.info("Looking for PLM on %s", port) _LOGGER.info("Looking for PLM on %s", port)
plm = yield from insteonplm.Connection.create(device=port, loop=hass.loop) conn = yield from insteonplm.Connection.create(
device=port,
loop=hass.loop,
workdir=hass.config.config_dir)
for device in overrides: plm = conn.protocol
for device_override in overrides:
# #
# Override the device default capabilities for a specific address # Override the device default capabilities for a specific address
# #
if isinstance(device['platform'], list): address = device_override.get('address')
plm.protocol.devices.add_override( for prop in device_override:
device['address'], 'capabilities', device['platform']) if prop in [CONF_CAT, CONF_SUBCAT]:
else: plm.devices.add_override(address, prop,
plm.protocol.devices.add_override( device_override[prop])
device['address'], 'capabilities', [device['platform']]) elif prop in [CONF_FIRMWARE, CONF_PRODUCT_KEY]:
plm.devices.add_override(address, CONF_PRODUCT_KEY,
device_override[prop])
hass.data['insteon_plm'] = plm hass.data['insteon_plm'] = plm
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, plm.close) hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, conn.close)
plm.protocol.devices.add_device_callback(async_plm_new_device, {}) plm.devices.add_device_callback(async_plm_new_device)
return True return True
def common_attributes(entity): State = collections.namedtuple('Product', 'stateType platform')
"""Return the device state attributes."""
attributes = {}
attributekeys = {
'address': 'INSTEON Address',
'description': 'Description',
'model': 'Model',
'cat': 'Category',
'subcat': 'Subcategory',
'firmware': 'Firmware',
'product_key': 'Product Key'
}
hexkeys = ['cat', 'subcat', 'firmware']
for key in attributekeys: class IPDB(object):
name = attributekeys[key] """Embodies the INSTEON Product Database static data and access methods."""
val = entity.get_attr(key)
if val is not None: def __init__(self):
if key in hexkeys: """Create the INSTEON Product Database (IPDB)."""
attributes[name] = hex(int(val)) from insteonplm.states.onOff import (OnOffSwitch,
else: OnOffSwitch_OutletTop,
attributes[name] = val OnOffSwitch_OutletBottom,
return attributes OpenClosedRelay)
from insteonplm.states.dimmable import (DimmableSwitch,
DimmableSwitch_Fan)
from insteonplm.states.sensor import (VariableSensor,
OnOffSensor,
SmokeCO2Sensor,
IoLincSensor)
self.states = [State(OnOffSwitch_OutletTop, 'switch'),
State(OnOffSwitch_OutletBottom, 'switch'),
State(OpenClosedRelay, 'switch'),
State(OnOffSwitch, 'switch'),
State(IoLincSensor, 'binary_sensor'),
State(SmokeCO2Sensor, 'sensor'),
State(OnOffSensor, 'binary_sensor'),
State(VariableSensor, 'sensor'),
State(DimmableSwitch_Fan, 'fan'),
State(DimmableSwitch, 'light')]
def __len__(self):
"""Return the number of INSTEON state types mapped to HA platforms."""
return len(self.states)
def __iter__(self):
"""Itterate through the INSTEON state types to HA platforms."""
for product in self.states:
yield product
def __getitem__(self, key):
"""Return a Home Assistant platform from an INSTEON state type."""
for state in self.states:
if isinstance(key, state.stateType):
return state
return None
class InsteonPLMEntity(Entity):
"""INSTEON abstract base entity."""
def __init__(self, device, state_key):
"""Initialize the INSTEON PLM binary sensor."""
self._insteon_device_state = device.states[state_key]
self._insteon_device = device
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def address(self):
"""Return the address of the node."""
return self._insteon_device.address.human
@property
def group(self):
"""Return the INSTEON group that the entity responds to."""
return self._insteon_device_state.group
@property
def name(self):
"""Return the name of the node (used for Entity_ID)."""
name = ''
if self._insteon_device_state.group == 0x01:
name = self._insteon_device.id
else:
name = '{:s}_{:d}'.format(self._insteon_device.id,
self._insteon_device_state.group)
return name
@property
def device_state_attributes(self):
"""Provide attributes for display on device card."""
attributes = {
'INSTEON Address': self.address,
'INSTEON Group': self.group
}
return attributes
@callback
def async_entity_update(self, deviceid, statename, val):
"""Receive notification from transport that new data exists."""
self.async_schedule_update_ha_state()
@asyncio.coroutine
def async_added_to_hass(self):
"""Register INSTEON update events."""
self._insteon_device_state.register_updates(
self.async_entity_update)

View File

@ -2,15 +2,14 @@
Support for Insteon lights via PowerLinc Modem. Support for Insteon lights via PowerLinc Modem.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/insteon_plm/ https://home-assistant.io/components/light.insteon_plm/
""" """
import logging
import asyncio import asyncio
import logging
from homeassistant.core import callback from homeassistant.components.insteon_plm import InsteonPLMEntity
from homeassistant.components.light import ( from homeassistant.components.light import (
ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light) ATTR_BRIGHTNESS, SUPPORT_BRIGHTNESS, Light)
from homeassistant.loader import get_component
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -24,96 +23,47 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Insteon PLM device.""" """Set up the Insteon PLM device."""
plm = hass.data['insteon_plm'] plm = hass.data['insteon_plm']
device_list = [] address = discovery_info['address']
for device in discovery_info: device = plm.devices[address]
name = device.get('address') state_key = discovery_info['state_key']
address = device.get('address_hex')
dimmable = bool('dimmable' in device.get('capabilities'))
_LOGGER.info("Registered %s with light platform", name) _LOGGER.debug('Adding device %s entity %s to Light platform',
device.address.hex, device.states[state_key].name)
device_list.append( new_entity = InsteonPLMDimmerDevice(device, state_key)
InsteonPLMDimmerDevice(hass, plm, address, name, dimmable)
)
async_add_devices(device_list) async_add_devices([new_entity])
class InsteonPLMDimmerDevice(Light): class InsteonPLMDimmerDevice(InsteonPLMEntity, Light):
"""A Class for an Insteon device.""" """A Class for an Insteon device."""
def __init__(self, hass, plm, address, name, dimmable):
"""Initialize the light."""
self._hass = hass
self._plm = plm.protocol
self._address = address
self._name = name
self._dimmable = dimmable
self._plm.add_update_callback(
self.async_light_update, {'address': self._address})
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def address(self):
"""Return the address of the node."""
return self._address
@property
def name(self):
"""Return the name of the node."""
return self._name
@property @property
def brightness(self): def brightness(self):
"""Return the brightness of this light between 0..255.""" """Return the brightness of this light between 0..255."""
onlevel = self._plm.get_device_attr(self._address, 'onlevel') onlevel = self._insteon_device_state.value
_LOGGER.debug("on level for %s is %s", self._address, onlevel)
return int(onlevel) return int(onlevel)
@property @property
def is_on(self): def is_on(self):
"""Return the boolean response if the node is on.""" """Return the boolean response if the node is on."""
onlevel = self._plm.get_device_attr(self._address, 'onlevel') return bool(self.brightness)
_LOGGER.debug("on level for %s is %s", self._address, onlevel)
return bool(onlevel)
@property @property
def supported_features(self): def supported_features(self):
"""Flag supported features.""" """Flag supported features."""
if self._dimmable: return SUPPORT_BRIGHTNESS
return SUPPORT_BRIGHTNESS
@property
def device_state_attributes(self):
"""Provide attributes for display on device card."""
insteon_plm = get_component('insteon_plm')
return insteon_plm.common_attributes(self)
def get_attr(self, key):
"""Return specified attribute for this device."""
return self._plm.get_device_attr(self.address, key)
@callback
def async_light_update(self, message):
"""Receive notification from transport that new data exists."""
_LOGGER.info("Received update callback from PLM for %s", self._address)
self._hass.async_add_job(self.async_update_ha_state())
@asyncio.coroutine @asyncio.coroutine
def async_turn_on(self, **kwargs): def async_turn_on(self, **kwargs):
"""Turn device on.""" """Turn device on."""
if ATTR_BRIGHTNESS in kwargs: if ATTR_BRIGHTNESS in kwargs:
brightness = int(kwargs[ATTR_BRIGHTNESS]) brightness = int(kwargs[ATTR_BRIGHTNESS])
self._insteon_device_state.set_level(brightness)
else: else:
brightness = MAX_BRIGHTNESS self._insteon_device_state.on()
self._plm.turn_on(self._address, brightness=brightness)
@asyncio.coroutine @asyncio.coroutine
def async_turn_off(self, **kwargs): def async_turn_off(self, **kwargs):
"""Turn device off.""" """Turn device off."""
self._plm.turn_off(self._address) self._insteon_device_state.off()

View File

@ -0,0 +1,36 @@
"""
Support for INSTEON dimmers via PowerLinc Modem.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/sensor.insteon_plm/
"""
import asyncio
import logging
from homeassistant.components.insteon_plm import InsteonPLMEntity
from homeassistant.helpers.entity import Entity
DEPENDENCIES = ['insteon_plm']
_LOGGER = logging.getLogger(__name__)
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the INSTEON PLM device class for the hass platform."""
plm = hass.data['insteon_plm']
address = discovery_info['address']
device = plm.devices[address]
state_key = discovery_info['state_key']
_LOGGER.debug('Adding device %s entity %s to Sensor platform',
device.address.hex, device.states[state_key].name)
new_entity = InsteonPLMSensorDevice(device, state_key)
async_add_devices([new_entity])
class InsteonPLMSensorDevice(InsteonPLMEntity, Entity):
"""A Class for an Insteon device."""

View File

@ -2,14 +2,13 @@
Support for INSTEON dimmers via PowerLinc Modem. Support for INSTEON dimmers via PowerLinc Modem.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/insteon_plm/ https://home-assistant.io/components/switch.insteon_plm/
""" """
import logging
import asyncio import asyncio
import logging
from homeassistant.core import callback from homeassistant.components.insteon_plm import InsteonPLMEntity
from homeassistant.components.switch import (SwitchDevice) from homeassistant.components.switch import SwitchDevice
from homeassistant.loader import get_component
DEPENDENCIES = ['insteon_plm'] DEPENDENCIES = ['insteon_plm']
@ -21,77 +20,54 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the INSTEON PLM device class for the hass platform.""" """Set up the INSTEON PLM device class for the hass platform."""
plm = hass.data['insteon_plm'] plm = hass.data['insteon_plm']
device_list = [] address = discovery_info['address']
for device in discovery_info: device = plm.devices[address]
name = device.get('address') state_key = discovery_info['state_key']
address = device.get('address_hex')
_LOGGER.info('Registered %s with switch platform.', name) state_name = device.states[state_key].name
device_list.append( _LOGGER.debug('Adding device %s entity %s to Switch platform',
InsteonPLMSwitchDevice(hass, plm, address, name) device.address.hex, device.states[state_key].name)
)
async_add_devices(device_list) new_entity = None
if state_name in ['lightOnOff', 'outletTopOnOff', 'outletBottomOnOff']:
new_entity = InsteonPLMSwitchDevice(device, state_key)
elif state_name == 'openClosedRelay':
new_entity = InsteonPLMOpenClosedDevice(device, state_key)
if new_entity is not None:
async_add_devices([new_entity])
class InsteonPLMSwitchDevice(SwitchDevice): class InsteonPLMSwitchDevice(InsteonPLMEntity, SwitchDevice):
"""A Class for an Insteon device.""" """A Class for an Insteon device."""
def __init__(self, hass, plm, address, name):
"""Initialize the switch."""
self._hass = hass
self._plm = plm.protocol
self._address = address
self._name = name
self._plm.add_update_callback(
self.async_switch_update, {'address': self._address})
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def address(self):
"""Return the address of the node."""
return self._address
@property
def name(self):
"""Return the name of the node."""
return self._name
@property @property
def is_on(self): def is_on(self):
"""Return the boolean response if the node is on.""" """Return the boolean response if the node is on."""
onlevel = self._plm.get_device_attr(self._address, 'onlevel') onlevel = self._insteon_device_state.value
_LOGGER.debug('on level for %s is %s', self._address, onlevel)
return bool(onlevel) return bool(onlevel)
@property
def device_state_attributes(self):
"""Provide attributes for display on device card."""
insteon_plm = get_component('insteon_plm')
return insteon_plm.common_attributes(self)
def get_attr(self, key):
"""Return specified attribute for this device."""
return self._plm.get_device_attr(self.address, key)
@callback
def async_switch_update(self, message):
"""Receive notification from transport that new data exists."""
_LOGGER.info('Received update callback from PLM for %s', self._address)
self._hass.async_add_job(self.async_update_ha_state())
@asyncio.coroutine @asyncio.coroutine
def async_turn_on(self, **kwargs): def async_turn_on(self, **kwargs):
"""Turn device on.""" """Turn device on."""
self._plm.turn_on(self._address) self._insteon_device_state.on()
@asyncio.coroutine @asyncio.coroutine
def async_turn_off(self, **kwargs): def async_turn_off(self, **kwargs):
"""Turn device off.""" """Turn device off."""
self._plm.turn_off(self._address) self._insteon_device_state.off()
class InsteonPLMOpenClosedDevice(InsteonPLMEntity, SwitchDevice):
"""A Class for an Insteon device."""
@asyncio.coroutine
def async_turn_on(self, **kwargs):
"""Turn device on."""
self._insteon_device_state.open()
@asyncio.coroutine
def async_turn_off(self, **kwargs):
"""Turn device off."""
self._insteon_device_state.close()

View File

@ -413,7 +413,7 @@ influxdb==5.0.0
insteonlocal==0.53 insteonlocal==0.53
# homeassistant.components.insteon_plm # homeassistant.components.insteon_plm
insteonplm==0.7.5 insteonplm==0.8.2
# homeassistant.components.verisure # homeassistant.components.verisure
jsonpath==0.75 jsonpath==0.75