Add All-Linking capabilities (#14065)
* Setup all-linking service * Remove extra line * Remove linefeed and tab escape chars * Add services delete_all_link, load_all_link_database and print_all_link_database * Check if reload is set * Confirm entity is InsteonPLMEntity before attempting to load or print ALDB * Debug load and print ALDB * Debug print aldb * Debug print_aldb * Get entity via platform * Track Insteon entities in component * Store entity list in hass.data * Add entity to hass.data * Add ref to hass in InsteonPLMEntity * Pass hass correctly to InsteonPLMBinarySensor * Fix reference to ALDBStatus.PARTIAL * Print ALDB record as string * Get ALDB record from memory address * Reformat ALDB log output * Add print_im_aldb service * Remove reference to self in print_aldb_to_log * Remove reference to self in print_aldb_to_log * Fix spelling issue with load_all_link_database service * Bump insteonplm to 0.9.1 * Changes from code review * Code review changes * Fix syntax error * Correct reference to cv.boolean and update requirements * Update requirements * Fix flake8 errors * Reload as boolean test * Remove hass from entity init
This commit is contained in:
parent
2e8eaf40f7
commit
64ba2c63c7
8 changed files with 171 additions and 9 deletions
|
@ -23,7 +23,7 @@ SENSOR_TYPES = {'openClosedSensor': 'opening',
|
|||
@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']
|
||||
plm = hass.data['insteon_plm'].get('plm')
|
||||
|
||||
address = discovery_info['address']
|
||||
device = plm.devices[address]
|
||||
|
|
|
@ -31,7 +31,7 @@ _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']
|
||||
plm = hass.data['insteon_plm'].get('plm')
|
||||
|
||||
address = discovery_info['address']
|
||||
device = plm.devices[address]
|
||||
|
|
|
@ -11,12 +11,13 @@ import voluptuous as vol
|
|||
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.const import (CONF_PORT, EVENT_HOMEASSISTANT_STOP,
|
||||
CONF_PLATFORM)
|
||||
CONF_PLATFORM,
|
||||
CONF_ENTITY_ID)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers import discovery
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
REQUIREMENTS = ['insteonplm==0.8.6']
|
||||
REQUIREMENTS = ['insteonplm==0.9.1']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -29,6 +30,17 @@ CONF_SUBCAT = 'subcat'
|
|||
CONF_FIRMWARE = 'firmware'
|
||||
CONF_PRODUCT_KEY = 'product_key'
|
||||
|
||||
SRV_ADD_ALL_LINK = 'add_all_link'
|
||||
SRV_DEL_ALL_LINK = 'delete_all_link'
|
||||
SRV_LOAD_ALDB = 'load_all_link_database'
|
||||
SRV_PRINT_ALDB = 'print_all_link_database'
|
||||
SRV_PRINT_IM_ALDB = 'print_im_all_link_database'
|
||||
SRV_ALL_LINK_GROUP = 'group'
|
||||
SRV_ALL_LINK_MODE = 'mode'
|
||||
SRV_LOAD_DB_RELOAD = 'reload'
|
||||
SRV_CONTROLLER = 'controller'
|
||||
SRV_RESPONDER = 'responder'
|
||||
|
||||
CONF_DEVICE_OVERRIDE_SCHEMA = vol.All(
|
||||
cv.deprecated(CONF_PLATFORM), vol.Schema({
|
||||
vol.Required(CONF_ADDRESS): cv.string,
|
||||
|
@ -47,6 +59,24 @@ CONFIG_SCHEMA = vol.Schema({
|
|||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
|
||||
ADD_ALL_LINK_SCHEMA = vol.Schema({
|
||||
vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255),
|
||||
vol.Required(SRV_ALL_LINK_MODE): vol.In([SRV_CONTROLLER, SRV_RESPONDER]),
|
||||
})
|
||||
|
||||
DEL_ALL_LINK_SCHEMA = vol.Schema({
|
||||
vol.Required(SRV_ALL_LINK_GROUP): vol.Range(min=0, max=255),
|
||||
})
|
||||
|
||||
LOAD_ALDB_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||
vol.Optional(SRV_LOAD_DB_RELOAD, default='false'): cv.boolean,
|
||||
})
|
||||
|
||||
PRINT_ALDB_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||
})
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_setup(hass, config):
|
||||
|
@ -54,6 +84,7 @@ def async_setup(hass, config):
|
|||
import insteonplm
|
||||
|
||||
ipdb = IPDB()
|
||||
plm = None
|
||||
|
||||
conf = config[DOMAIN]
|
||||
port = conf.get(CONF_PORT)
|
||||
|
@ -79,6 +110,60 @@ def async_setup(hass, config):
|
|||
'state_key': state_key},
|
||||
hass_config=config))
|
||||
|
||||
def add_all_link(service):
|
||||
"""Add an INSTEON All-Link between two devices."""
|
||||
group = service.data.get(SRV_ALL_LINK_GROUP)
|
||||
mode = service.data.get(SRV_ALL_LINK_MODE)
|
||||
link_mode = 1 if mode.lower() == SRV_CONTROLLER else 0
|
||||
plm.start_all_linking(link_mode, group)
|
||||
|
||||
def del_all_link(service):
|
||||
"""Delete an INSTEON All-Link between two devices."""
|
||||
group = service.data.get(SRV_ALL_LINK_GROUP)
|
||||
plm.start_all_linking(255, group)
|
||||
|
||||
def load_aldb(service):
|
||||
"""Load the device All-Link database."""
|
||||
entity_id = service.data.get(CONF_ENTITY_ID)
|
||||
reload = service.data.get(SRV_LOAD_DB_RELOAD)
|
||||
entities = hass.data[DOMAIN].get('entities')
|
||||
entity = entities.get(entity_id)
|
||||
if entity:
|
||||
entity.load_aldb(reload)
|
||||
else:
|
||||
_LOGGER.error('Entity %s is not an INSTEON device', entity_id)
|
||||
|
||||
def print_aldb(service):
|
||||
"""Print the All-Link Database for a device."""
|
||||
# For now this sends logs to the log file.
|
||||
# Furture direction is to create an INSTEON control panel.
|
||||
entity_id = service.data.get(CONF_ENTITY_ID)
|
||||
entities = hass.data[DOMAIN].get('entities')
|
||||
entity = entities.get(entity_id)
|
||||
if entity:
|
||||
entity.print_aldb()
|
||||
else:
|
||||
_LOGGER.error('Entity %s is not an INSTEON device', entity_id)
|
||||
|
||||
def print_im_aldb(service):
|
||||
"""Print the All-Link Database for a device."""
|
||||
# For now this sends logs to the log file.
|
||||
# Furture direction is to create an INSTEON control panel.
|
||||
print_aldb_to_log(plm.aldb)
|
||||
|
||||
def _register_services():
|
||||
hass.services.register(DOMAIN, SRV_ADD_ALL_LINK, add_all_link,
|
||||
schema=ADD_ALL_LINK_SCHEMA)
|
||||
hass.services.register(DOMAIN, SRV_DEL_ALL_LINK, del_all_link,
|
||||
schema=DEL_ALL_LINK_SCHEMA)
|
||||
hass.services.register(DOMAIN, SRV_LOAD_ALDB, load_aldb,
|
||||
schema=LOAD_ALDB_SCHEMA)
|
||||
hass.services.register(DOMAIN, SRV_PRINT_ALDB, print_aldb,
|
||||
schema=PRINT_ALDB_SCHEMA)
|
||||
hass.services.register(DOMAIN, SRV_PRINT_IM_ALDB, print_im_aldb,
|
||||
schema=None)
|
||||
_LOGGER.debug("Insteon_plm Services registered")
|
||||
|
||||
_LOGGER.info("Looking for PLM on %s", port)
|
||||
conn = yield from insteonplm.Connection.create(
|
||||
device=port,
|
||||
|
@ -100,11 +185,14 @@ def async_setup(hass, config):
|
|||
plm.devices.add_override(address, CONF_PRODUCT_KEY,
|
||||
device_override[prop])
|
||||
|
||||
hass.data['insteon_plm'] = plm
|
||||
hass.data[DOMAIN] = {}
|
||||
hass.data[DOMAIN]['plm'] = plm
|
||||
hass.data[DOMAIN]['entities'] = {}
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, conn.close)
|
||||
|
||||
plm.devices.add_device_callback(async_plm_new_device)
|
||||
hass.async_add_job(_register_services)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -169,6 +257,7 @@ class InsteonPLMEntity(Entity):
|
|||
"""Initialize the INSTEON PLM binary sensor."""
|
||||
self._insteon_device_state = device.states[state_key]
|
||||
self._insteon_device = device
|
||||
self._insteon_device.aldb.add_loaded_callback(self._aldb_loaded)
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
|
@ -215,3 +304,44 @@ class InsteonPLMEntity(Entity):
|
|||
"""Register INSTEON update events."""
|
||||
self._insteon_device_state.register_updates(
|
||||
self.async_entity_update)
|
||||
self.hass.data[DOMAIN]['entities'][self.entity_id] = self
|
||||
|
||||
def load_aldb(self, reload=False):
|
||||
"""Load the device All-Link Database."""
|
||||
if reload:
|
||||
self._insteon_device.aldb.clear()
|
||||
self._insteon_device.read_aldb()
|
||||
|
||||
def print_aldb(self):
|
||||
"""Print the device ALDB to the log file."""
|
||||
print_aldb_to_log(self._insteon_device.aldb)
|
||||
|
||||
@callback
|
||||
def _aldb_loaded(self):
|
||||
"""All-Link Database loaded for the device."""
|
||||
self.print_aldb()
|
||||
|
||||
|
||||
def print_aldb_to_log(aldb):
|
||||
"""Print the All-Link Database to the log file."""
|
||||
from insteonplm.devices import ALDBStatus
|
||||
_LOGGER.info('ALDB load status is %s', aldb.status.name)
|
||||
if aldb.status not in [ALDBStatus.LOADED, ALDBStatus.PARTIAL]:
|
||||
_LOGGER.warning('Device All-Link database not loaded')
|
||||
_LOGGER.warning('Use service insteon_plm.load_aldb first')
|
||||
return
|
||||
|
||||
_LOGGER.info('RecID In Use Mode HWM Group Address Data 1 Data 2 Data 3')
|
||||
_LOGGER.info('----- ------ ---- --- ----- -------- ------ ------ ------')
|
||||
for mem_addr in aldb:
|
||||
rec = aldb[mem_addr]
|
||||
# For now we write this to the log
|
||||
# Roadmap is to create a configuration panel
|
||||
in_use = 'Y' if rec.control_flags.is_in_use else 'N'
|
||||
mode = 'C' if rec.control_flags.is_controller else 'R'
|
||||
hwm = 'Y' if rec.control_flags.is_high_water_mark else 'N'
|
||||
_LOGGER.info(' {:04x} {:s} {:s} {:s} {:3d} {:s}'
|
||||
' {:3d} {:3d} {:3d}'.format(
|
||||
rec.mem_addr, in_use, mode, hwm,
|
||||
rec.group, rec.address.human,
|
||||
rec.data1, rec.data2, rec.data3))
|
32
homeassistant/components/insteon_plm/services.yaml
Normal file
32
homeassistant/components/insteon_plm/services.yaml
Normal file
|
@ -0,0 +1,32 @@
|
|||
add_all_link:
|
||||
description: Tells the Insteom Modem (IM) start All-Linking mode. Once the the IM is in All-Linking mode, press the link button on the device to complete All-Linking.
|
||||
fields:
|
||||
group:
|
||||
description: All-Link group number.
|
||||
example: 1
|
||||
mode:
|
||||
description: Linking mode controller - IM is controller responder - IM is responder
|
||||
example: 'controller'
|
||||
delete_all_link:
|
||||
description: Tells the Insteon Modem (IM) to remove an All-Link record from the All-Link Database of the IM and a device. Once the IM is set to delete the link, press the link button on the corresponding device to complete the process.
|
||||
fields:
|
||||
group:
|
||||
description: All-Link group number.
|
||||
example: 1
|
||||
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 inconsistant. This may take a LONG time and may need to be repeated to obtain all records.
|
||||
fields:
|
||||
entity_id:
|
||||
description: Name of the device to print
|
||||
example: 'light.1a2b3c'
|
||||
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.
|
||||
example: 'true'
|
||||
print_all_link_database:
|
||||
description: Print the All-Link Database for a device. Requires that the All-Link Database is loaded into memory.
|
||||
fields:
|
||||
entity_id:
|
||||
description: Name of the device to print
|
||||
example: 'light.1a2b3c'
|
||||
print_im_all_link_database:
|
||||
description: Print the All-Link Database for the INSTEON Modem (IM).
|
|
@ -21,7 +21,7 @@ MAX_BRIGHTNESS = 255
|
|||
@asyncio.coroutine
|
||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||
"""Set up the Insteon PLM device."""
|
||||
plm = hass.data['insteon_plm']
|
||||
plm = hass.data['insteon_plm'].get('plm')
|
||||
|
||||
address = discovery_info['address']
|
||||
device = plm.devices[address]
|
||||
|
|
|
@ -18,7 +18,7 @@ _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']
|
||||
plm = hass.data['insteon_plm'].get('plm')
|
||||
|
||||
address = discovery_info['address']
|
||||
device = plm.devices[address]
|
||||
|
|
|
@ -18,7 +18,7 @@ _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']
|
||||
plm = hass.data['insteon_plm'].get('plm')
|
||||
|
||||
address = discovery_info['address']
|
||||
device = plm.devices[address]
|
||||
|
|
|
@ -446,7 +446,7 @@ influxdb==5.0.0
|
|||
insteonlocal==0.53
|
||||
|
||||
# homeassistant.components.insteon_plm
|
||||
insteonplm==0.8.6
|
||||
insteonplm==0.9.1
|
||||
|
||||
# homeassistant.components.verisure
|
||||
jsonpath==0.75
|
||||
|
|
Loading…
Add table
Reference in a new issue