Fix wrapper and S_BINARY and bump req. version

* Wrap existing SerialGateway instance instead of subclassing
	SerialGatewat class.
* Add S_BINARY in switch platform only in version 1.5 of mysenors api.
* Use version 0.4 of pymysensors.
* Show gateway port as state attribute.
This commit is contained in:
MartinHjelmare 2016-01-10 04:10:38 +01:00
parent 4c4e5d5f47
commit 2d8cf7de44
4 changed files with 46 additions and 30 deletions

View file

@ -12,7 +12,8 @@ New features:
New MySensors component. New MySensors component.
Updated MySensors Sensor platform. Updated MySensors Sensor platform.
New MySensors Switch platform. New MySensors Switch platform. Currently only in optimistic mode (compare
with MQTT).
Multiple gateways are now supported. Multiple gateways are now supported.
Configuration.yaml: Configuration.yaml:
@ -29,11 +30,6 @@ mysensors:
""" """
import logging import logging
try:
import mysensors.mysensors as mysensors
except ImportError:
mysensors = None
from homeassistant.helpers import validate_config from homeassistant.helpers import validate_config
import homeassistant.bootstrap as bootstrap import homeassistant.bootstrap as bootstrap
@ -55,10 +51,11 @@ DOMAIN = 'mysensors'
DEPENDENCIES = [] DEPENDENCIES = []
REQUIREMENTS = [ REQUIREMENTS = [
'https://github.com/theolind/pymysensors/archive/' 'https://github.com/theolind/pymysensors/archive/'
'2aa8f32908e8c5bb3e5c77c5851db778f8635792.zip#pymysensors==0.3'] '005bff4c5ca7a56acd30e816bc3bcdb5cb2d46fd.zip#pymysensors==0.4']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTR_NODE_ID = 'node_id' ATTR_NODE_ID = 'node_id'
ATTR_CHILD_ID = 'child_id' ATTR_CHILD_ID = 'child_id'
ATTR_PORT = 'port'
GATEWAYS = None GATEWAYS = None
SCAN_INTERVAL = 30 SCAN_INTERVAL = 30
@ -82,21 +79,22 @@ def setup(hass, config):
_LOGGER): _LOGGER):
return False return False
global mysensors # pylint: disable=invalid-name import mysensors.mysensors as mysensors
if mysensors is None:
import mysensors.mysensors as _mysensors
mysensors = _mysensors
version = str(config[DOMAIN].get(CONF_VERSION, DEFAULT_VERSION)) version = str(config[DOMAIN].get(CONF_VERSION, DEFAULT_VERSION))
is_metric = (hass.config.temperature_unit == TEMP_CELCIUS) is_metric = (hass.config.temperature_unit == TEMP_CELCIUS)
def setup_gateway(port, persistence, persistence_file, version): def setup_gateway(port, persistence, persistence_file, version):
"""Return gateway after setup of the gateway.""" """Return gateway after setup of the gateway."""
gateway = GatewayWrapper( gateway = mysensors.SerialGateway(port, event_callback=None,
port, persistence, persistence_file, version) persistence=persistence,
# pylint: disable=attribute-defined-outside-init persistence_file=persistence_file,
protocol_version=version)
gateway.metric = is_metric gateway.metric = is_metric
gateway.debug = config[DOMAIN].get(CONF_DEBUG, False) gateway.debug = config[DOMAIN].get(CONF_DEBUG, False)
gateway = GatewayWrapper(gateway, version)
# pylint: disable=attribute-defined-outside-init
gateway.event_callback = gateway.callback_factory()
def gw_start(event): def gw_start(event):
"""Callback to trigger start of gateway and any persistence.""" """Callback to trigger start of gateway and any persistence."""
@ -172,30 +170,46 @@ def pf_callback_factory(
return mysensors_callback return mysensors_callback
class GatewayWrapper(mysensors.SerialGateway): class GatewayWrapper(object):
"""Gateway wrapper class, by subclassing serial gateway.""" """Gateway wrapper class, by subclassing serial gateway."""
def __init__(self, port, persistence, persistence_file, version): def __init__(self, gateway, version):
"""Setup class attributes on instantiation. """Setup class attributes on instantiation.
Args: Args:
port: Port of gateway to wrap. gateway (mysensors.SerialGateway): Gateway to wrap.
persistence: Persistence, true or false. version (str): Version of mysensors API.
persistence_file: File to store persistence info.
version: Version of mysensors API.
Attributes: Attributes:
_wrapped_gateway (mysensors.SerialGateway): Wrapped gateway.
version (str): Version of mysensors API. version (str): Version of mysensors API.
platform_callbacks (list): Callback functions, one per platform. platform_callbacks (list): Callback functions, one per platform.
const (module): Mysensors API constants. const (module): Mysensors API constants.
__initialised (bool): True if GatewayWrapper is initialised.
""" """
super().__init__(port, event_callback=self.callback_factory(), self._wrapped_gateway = gateway
persistence=persistence,
persistence_file=persistence_file,
protocol_version=version)
self.version = version self.version = version
self.platform_callbacks = [] self.platform_callbacks = []
self.const = self.get_const() self.const = self.get_const()
self.__initialised = True
def __getattr__(self, name):
"""See if this object has attribute name."""
# Do not use hasattr, it goes into infinite recurrsion
if name in self.__dict__:
# this object has it
return getattr(self, name)
# proxy to the wrapped object
return getattr(self._wrapped_gateway, name)
def __setattr__(self, name, value):
"""See if this object has attribute name then set to value."""
if '_GatewayWrapper__initialised' not in self.__dict__:
return object.__setattr__(self, name, value)
elif name in self.__dict__:
object.__setattr__(self, name, value)
else:
object.__setattr__(self._wrapped_gateway, name, value)
def get_const(self): def get_const(self):
"""Get mysensors API constants.""" """Get mysensors API constants."""

View file

@ -78,14 +78,14 @@ class MySensorsSensor(Entity):
"""Setup class attributes on instantiation. """Setup class attributes on instantiation.
Args: Args:
gateway (str): Gateway. gateway (GatewayWrapper): Gateway object.
node_id (str): Id of node. node_id (str): Id of node.
child_id (str): Id of child. child_id (str): Id of child.
name (str): Entity name. name (str): Entity name.
value_type (str): Value type of child. Value is entity state. value_type (str): Value type of child. Value is entity state.
Attributes: Attributes:
gateway (str): Gateway. gateway (GatewayWrapper): Gateway object.
node_id (str): Id of node. node_id (str): Id of node.
child_id (str): Id of child. child_id (str): Id of child.
_name (str): Entity name. _name (str): Entity name.
@ -154,6 +154,7 @@ class MySensorsSensor(Entity):
def state_attributes(self): def state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""
data = { data = {
mysensors.ATTR_PORT: self.gateway.port,
mysensors.ATTR_NODE_ID: self.node_id, mysensors.ATTR_NODE_ID: self.node_id,
mysensors.ATTR_CHILD_ID: self.child_id, mysensors.ATTR_CHILD_ID: self.child_id,
ATTR_BATTERY_LEVEL: self.battery_level, ATTR_BATTERY_LEVEL: self.battery_level,

View file

@ -36,7 +36,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
gateway.const.Presentation.S_MOTION, gateway.const.Presentation.S_MOTION,
gateway.const.Presentation.S_SMOKE, gateway.const.Presentation.S_SMOKE,
gateway.const.Presentation.S_LIGHT, gateway.const.Presentation.S_LIGHT,
gateway.const.Presentation.S_BINARY,
gateway.const.Presentation.S_LOCK, gateway.const.Presentation.S_LOCK,
] ]
v_types = [ v_types = [
@ -46,6 +45,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
] ]
if float(gateway.version) >= 1.5: if float(gateway.version) >= 1.5:
s_types.extend([ s_types.extend([
gateway.const.Presentation.S_BINARY,
gateway.const.Presentation.S_SPRINKLER, gateway.const.Presentation.S_SPRINKLER,
gateway.const.Presentation.S_WATER_LEAK, gateway.const.Presentation.S_WATER_LEAK,
gateway.const.Presentation.S_SOUND, gateway.const.Presentation.S_SOUND,
@ -68,14 +68,14 @@ class MySensorsSwitch(SwitchDevice):
"""Setup class attributes on instantiation. """Setup class attributes on instantiation.
Args: Args:
port (str): Gateway port. gateway (GatewayWrapper): Gateway object.
node_id (str): Id of node. node_id (str): Id of node.
child_id (str): Id of child. child_id (str): Id of child.
name (str): Entity name. name (str): Entity name.
value_type (str): Value type of child. Value is entity state. value_type (str): Value type of child. Value is entity state.
Attributes: Attributes:
port (str): Gateway port. gateway (GatewayWrapper): Gateway object
node_id (str): Id of node. node_id (str): Id of node.
child_id (str): Id of child. child_id (str): Id of child.
_name (str): Entity name. _name (str): Entity name.
@ -112,6 +112,7 @@ class MySensorsSwitch(SwitchDevice):
def state_attributes(self): def state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""
data = { data = {
mysensors.ATTR_PORT: self.gateway.port,
mysensors.ATTR_NODE_ID: self.node_id, mysensors.ATTR_NODE_ID: self.node_id,
mysensors.ATTR_CHILD_ID: self.child_id, mysensors.ATTR_CHILD_ID: self.child_id,
ATTR_BATTERY_LEVEL: self.battery_level, ATTR_BATTERY_LEVEL: self.battery_level,

View file

@ -90,7 +90,7 @@ https://github.com/bashwork/pymodbus/archive/d7fc4f1cc975631e0a9011390e8017f64b6
paho-mqtt==1.1 paho-mqtt==1.1
# homeassistant.components.mysensors # homeassistant.components.mysensors
https://github.com/theolind/pymysensors/archive/2aa8f32908e8c5bb3e5c77c5851db778f8635792.zip#pymysensors==0.3 https://github.com/theolind/pymysensors/archive/005bff4c5ca7a56acd30e816bc3bcdb5cb2d46fd.zip#pymysensors==0.4
# homeassistant.components.notify.pushbullet # homeassistant.components.notify.pushbullet
pushbullet.py==0.9.0 pushbullet.py==0.9.0