Upgrade insteonplm to 0.16.0 and add INSTEON scene triggering (#24765)

* Upgrade insteonplm to 0.16.0 and add INSTEON scene triggering

* Fix spacing issue

* Dummy commit to trigger CLA

* Remove dummy change

* Code review changes

* Use ENTITY_MATCH_ALL keyword from const and lint cleanup

* Make entity method print_aldb private
This commit is contained in:
Tom Harris 2019-07-07 14:31:04 -04:00 committed by Martin Hjelmare
parent b0dc782c98
commit 0595fc3097
4 changed files with 76 additions and 25 deletions

View File

@ -7,15 +7,18 @@ import voluptuous as vol
from homeassistant.const import ( from homeassistant.const import (
CONF_ADDRESS, CONF_ENTITY_ID, CONF_HOST, CONF_PLATFORM, CONF_PORT, CONF_ADDRESS, CONF_ENTITY_ID, CONF_HOST, CONF_PLATFORM, CONF_PORT,
EVENT_HOMEASSISTANT_STOP) ENTITY_MATCH_ALL, EVENT_HOMEASSISTANT_STOP)
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from homeassistant.helpers.dispatcher import (
dispatcher_send, async_dispatcher_connect)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = 'insteon' DOMAIN = 'insteon'
INSTEON_ENTITIES = 'entities'
CONF_IP_PORT = 'ip_port' CONF_IP_PORT = 'ip_port'
CONF_HUB_USERNAME = 'username' CONF_HUB_USERNAME = 'username'
@ -49,6 +52,11 @@ SRV_LOAD_DB_RELOAD = 'reload'
SRV_CONTROLLER = 'controller' SRV_CONTROLLER = 'controller'
SRV_RESPONDER = 'responder' SRV_RESPONDER = 'responder'
SRV_HOUSECODE = 'housecode' SRV_HOUSECODE = 'housecode'
SRV_SCENE_ON = 'scene_on'
SRV_SCENE_OFF = 'scene_off'
SIGNAL_LOAD_ALDB = 'load_aldb'
SIGNAL_PRINT_ALDB = 'print_aldb'
HOUSECODES = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', HOUSECODES = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p'] 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']
@ -84,6 +92,7 @@ CONF_DEVICE_OVERRIDE_SCHEMA = vol.All(
vol.Optional(CONF_PLATFORM): cv.string, vol.Optional(CONF_PLATFORM): cv.string,
})) }))
CONF_X10_SCHEMA = vol.All( CONF_X10_SCHEMA = vol.All(
vol.Schema({ vol.Schema({
vol.Required(CONF_HOUSECODE): cv.string, vol.Required(CONF_HOUSECODE): cv.string,
@ -92,6 +101,7 @@ CONF_X10_SCHEMA = vol.All(
vol.Optional(CONF_DIM_STEPS): vol.Range(min=2, max=255) vol.Optional(CONF_DIM_STEPS): vol.Range(min=2, max=255)
})) }))
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.All( DOMAIN: vol.All(
vol.Schema( vol.Schema(
@ -121,23 +131,32 @@ ADD_ALL_LINK_SCHEMA = vol.Schema({
vol.Required(SRV_ALL_LINK_MODE): vol.In([SRV_CONTROLLER, SRV_RESPONDER]), vol.Required(SRV_ALL_LINK_MODE): vol.In([SRV_CONTROLLER, SRV_RESPONDER]),
}) })
DEL_ALL_LINK_SCHEMA = vol.Schema({ DEL_ALL_LINK_SCHEMA = vol.Schema({
vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255), vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255),
}) })
LOAD_ALDB_SCHEMA = vol.Schema({ LOAD_ALDB_SCHEMA = vol.Schema({
vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Required(CONF_ENTITY_ID): vol.Any(cv.entity_id, ENTITY_MATCH_ALL),
vol.Optional(SRV_LOAD_DB_RELOAD, default='false'): cv.boolean, vol.Optional(SRV_LOAD_DB_RELOAD, default=False): cv.boolean,
}) })
PRINT_ALDB_SCHEMA = vol.Schema({ PRINT_ALDB_SCHEMA = vol.Schema({
vol.Required(CONF_ENTITY_ID): cv.entity_id, vol.Required(CONF_ENTITY_ID): cv.entity_id,
}) })
X10_HOUSECODE_SCHEMA = vol.Schema({ X10_HOUSECODE_SCHEMA = vol.Schema({
vol.Required(SRV_HOUSECODE): vol.In(HOUSECODES), vol.Required(SRV_HOUSECODE): vol.In(HOUSECODES),
}) })
TRIGGER_SCENE_SCHEMA = vol.Schema({
vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255)})
STATE_NAME_LABEL_MAP = { STATE_NAME_LABEL_MAP = {
'keypadButtonA': 'Button A', 'keypadButtonA': 'Button A',
'keypadButtonB': 'Button B', 'keypadButtonB': 'Button B',
@ -237,26 +256,26 @@ async def async_setup(hass, config):
def load_aldb(service): def load_aldb(service):
"""Load the device All-Link database.""" """Load the device All-Link database."""
entity_id = service.data.get(CONF_ENTITY_ID) entity_id = service.data[CONF_ENTITY_ID]
reload = service.data.get(SRV_LOAD_DB_RELOAD) reload = service.data[SRV_LOAD_DB_RELOAD]
entities = hass.data[DOMAIN].get('entities') if entity_id.lower() == ENTITY_MATCH_ALL:
entity = entities.get(entity_id) for entity_id in hass.data[DOMAIN].get(INSTEON_ENTITIES):
if entity: _send_load_aldb_signal(entity_id, reload)
entity.load_aldb(reload)
else: else:
_LOGGER.error('Entity %s is not an INSTEON device', entity_id) _send_load_aldb_signal(entity_id, reload)
def _send_load_aldb_signal(entity_id, reload):
"""Send the load All-Link database signal to INSTEON entity."""
signal = '{}_{}'.format(entity_id, SIGNAL_LOAD_ALDB)
dispatcher_send(hass, signal, reload)
def print_aldb(service): def print_aldb(service):
"""Print the All-Link Database for a device.""" """Print the All-Link Database for a device."""
# For now this sends logs to the log file. # For now this sends logs to the log file.
# Furture direction is to create an INSTEON control panel. # Furture direction is to create an INSTEON control panel.
entity_id = service.data.get(CONF_ENTITY_ID) entity_id = service.data[CONF_ENTITY_ID]
entities = hass.data[DOMAIN].get('entities') signal = '{}_{}'.format(entity_id, SIGNAL_PRINT_ALDB)
entity = entities.get(entity_id) dispatcher_send(hass, signal)
if entity:
entity.print_aldb()
else:
_LOGGER.error('Entity %s is not an INSTEON device', entity_id)
def print_im_aldb(service): def print_im_aldb(service):
"""Print the All-Link Database for a device.""" """Print the All-Link Database for a device."""
@ -279,6 +298,16 @@ async def async_setup(hass, config):
housecode = service.data.get(SRV_HOUSECODE) housecode = service.data.get(SRV_HOUSECODE)
insteon_modem.x10_all_lights_on(housecode) insteon_modem.x10_all_lights_on(housecode)
def scene_on(service):
"""Trigger an INSTEON scene ON."""
group = service.data.get(SRV_ALL_LINK_GROUP)
insteon_modem.trigger_group_on(group)
def scene_off(service):
"""Trigger an INSTEON scene ON."""
group = service.data.get(SRV_ALL_LINK_GROUP)
insteon_modem.trigger_group_off(group)
def _register_services(): def _register_services():
hass.services.register(DOMAIN, SRV_ADD_ALL_LINK, add_all_link, hass.services.register(DOMAIN, SRV_ADD_ALL_LINK, add_all_link,
schema=ADD_ALL_LINK_SCHEMA) schema=ADD_ALL_LINK_SCHEMA)
@ -299,6 +328,12 @@ async def async_setup(hass, config):
hass.services.register(DOMAIN, SRV_X10_ALL_LIGHTS_ON, hass.services.register(DOMAIN, SRV_X10_ALL_LIGHTS_ON,
x10_all_lights_on, x10_all_lights_on,
schema=X10_HOUSECODE_SCHEMA) schema=X10_HOUSECODE_SCHEMA)
hass.services.register(DOMAIN, SRV_SCENE_ON,
scene_on,
schema=TRIGGER_SCENE_SCHEMA)
hass.services.register(DOMAIN, SRV_SCENE_OFF,
scene_off,
schema=TRIGGER_SCENE_SCHEMA)
_LOGGER.debug("Insteon Services registered") _LOGGER.debug("Insteon Services registered")
def _fire_button_on_off_event(address, group, val): def _fire_button_on_off_event(address, group, val):
@ -352,7 +387,7 @@ async def async_setup(hass, config):
hass.data[DOMAIN] = {} hass.data[DOMAIN] = {}
hass.data[DOMAIN]['modem'] = insteon_modem hass.data[DOMAIN]['modem'] = insteon_modem
hass.data[DOMAIN]['entities'] = {} hass.data[DOMAIN][INSTEON_ENTITIES] = {}
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, conn.close) hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, conn.close)
@ -547,22 +582,26 @@ class InsteonEntity(Entity):
self._insteon_device_state.name) self._insteon_device_state.name)
self._insteon_device_state.register_updates( self._insteon_device_state.register_updates(
self.async_entity_update) self.async_entity_update)
self.hass.data[DOMAIN]['entities'][self.entity_id] = self self.hass.data[DOMAIN][INSTEON_ENTITIES][self.entity_id] = self
load_signal = '{}_{}'.format(self.entity_id, SIGNAL_LOAD_ALDB)
async_dispatcher_connect(self.hass, load_signal, self._load_aldb)
print_signal = '{}_{}'.format(self.entity_id, SIGNAL_PRINT_ALDB)
async_dispatcher_connect(self.hass, print_signal, self._print_aldb)
def load_aldb(self, reload=False): def _load_aldb(self, reload=False):
"""Load the device All-Link Database.""" """Load the device All-Link Database."""
if reload: if reload:
self._insteon_device.aldb.clear() self._insteon_device.aldb.clear()
self._insteon_device.read_aldb() self._insteon_device.read_aldb()
def print_aldb(self): def _print_aldb(self):
"""Print the device ALDB to the log file.""" """Print the device ALDB to the log file."""
print_aldb_to_log(self._insteon_device.aldb) print_aldb_to_log(self._insteon_device.aldb)
@callback @callback
def _aldb_loaded(self): def _aldb_loaded(self):
"""All-Link Database loaded for the device.""" """All-Link Database loaded for the device."""
self.print_aldb() self._print_aldb()
def _get_label(self): def _get_label(self):
"""Get the device label for grouped devices.""" """Get the device label for grouped devices."""

View File

@ -3,7 +3,7 @@
"name": "Insteon", "name": "Insteon",
"documentation": "https://www.home-assistant.io/components/insteon", "documentation": "https://www.home-assistant.io/components/insteon",
"requirements": [ "requirements": [
"insteonplm==0.15.4" "insteonplm==0.16.0"
], ],
"dependencies": [], "dependencies": [],
"codeowners": [] "codeowners": []

View File

@ -17,7 +17,7 @@ load_all_link_database:
description: Load the All-Link Database for a device. WARNING - Loading a device All-LInk database is very time consuming and inconsistent. This may take a LONG time and may need to be repeated to obtain all records. description: Load the All-Link Database for a device. WARNING - Loading a device All-LInk database is very time consuming and inconsistent. This may take a LONG time and may need to be repeated to obtain all records.
fields: fields:
entity_id: entity_id:
description: Name of the device to print description: Name of the device to load. Use "all" to load the database of all devices.
example: 'light.1a2b3c' example: 'light.1a2b3c'
reload: reload:
description: Reload all records. If true the current records are cleared from memory (does not effect the device) and the records are reloaded. If false the existing records are left in place and only missing records are added. Default is false. description: Reload all records. If true the current records are cleared from memory (does not effect the device) and the records are reloaded. If false the existing records are left in place and only missing records are added. Default is false.
@ -48,3 +48,15 @@ x10_all_lights_off:
housecode: housecode:
description: X10 house code description: X10 house code
example: c example: c
scene_on:
description: Trigger an INSTEON scene to turn ON.
fields:
group:
description: INSTEON group or scene number
example: 26
scene_off:
description: Trigger an INSTEON scene to turn OFF.
fields:
group:
description: INSTEON group or scene number
example: 26

View File

@ -650,7 +650,7 @@ incomfort-client==0.3.0
influxdb==5.2.0 influxdb==5.2.0
# homeassistant.components.insteon # homeassistant.components.insteon
insteonplm==0.15.4 insteonplm==0.16.0
# homeassistant.components.iperf3 # homeassistant.components.iperf3
iperf3==0.1.10 iperf3==0.1.10