diff --git a/homeassistant/components/zigbee/__init__.py b/homeassistant/components/zigbee/__init__.py index fd9b42398fe..2fa8291538e 100644 --- a/homeassistant/components/zigbee/__init__.py +++ b/homeassistant/components/zigbee/__init__.py @@ -33,20 +33,8 @@ DEFAULT_DEVICE = "/dev/ttyUSB0" DEFAULT_BAUD = 9600 DEFAULT_ADC_MAX_VOLTS = 1.2 -# Copied from xbee_helper during setup() -GPIO_DIGITAL_OUTPUT_LOW = None -GPIO_DIGITAL_OUTPUT_HIGH = None -ADC_PERCENTAGE = None -DIGITAL_PINS = None -ANALOG_PINS = None -CONVERT_ADC = None -ZIGBEE_EXCEPTION = None -ZIGBEE_TX_FAILURE = None - ATTR_FRAME = "frame" -DEVICE = None - CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.Schema( @@ -71,24 +59,6 @@ PLATFORM_SCHEMA = vol.Schema( def setup(hass, config): """Set up the connection to the Zigbee device.""" - global DEVICE # pylint: disable=global-statement - global GPIO_DIGITAL_OUTPUT_LOW # pylint: disable=global-statement - global GPIO_DIGITAL_OUTPUT_HIGH # pylint: disable=global-statement - global ADC_PERCENTAGE # pylint: disable=global-statement - global DIGITAL_PINS # pylint: disable=global-statement - global ANALOG_PINS # pylint: disable=global-statement - global CONVERT_ADC # pylint: disable=global-statement - global ZIGBEE_EXCEPTION # pylint: disable=global-statement - global ZIGBEE_TX_FAILURE # pylint: disable=global-statement - - GPIO_DIGITAL_OUTPUT_LOW = xb_const.GPIO_DIGITAL_OUTPUT_LOW - GPIO_DIGITAL_OUTPUT_HIGH = xb_const.GPIO_DIGITAL_OUTPUT_HIGH - ADC_PERCENTAGE = xb_const.ADC_PERCENTAGE - DIGITAL_PINS = xb_const.DIGITAL_PINS - ANALOG_PINS = xb_const.ANALOG_PINS - CONVERT_ADC = convert_adc - ZIGBEE_EXCEPTION = ZigBeeException - ZIGBEE_TX_FAILURE = ZigBeeTxFailure usb_device = config[DOMAIN].get(CONF_DEVICE, DEFAULT_DEVICE) baud = int(config[DOMAIN].get(CONF_BAUD, DEFAULT_BAUD)) @@ -97,8 +67,11 @@ def setup(hass, config): except SerialException as exc: _LOGGER.exception("Unable to open serial port for Zigbee: %s", exc) return False - DEVICE = ZigBee(ser) - hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, close_serial_port) + zigbee_device = ZigBee(ser) + + def close_serial_port(*args): + """Close the serial port we're using to communicate with the Zigbee.""" + zigbee_device.zb.serial.close() def _frame_received(frame): """Run when a Zigbee frame is received. @@ -108,16 +81,13 @@ def setup(hass, config): """ dispatcher_send(hass, SIGNAL_ZIGBEE_FRAME_RECEIVED, frame) - DEVICE.add_frame_rx_handler(_frame_received) + hass.data[DOMAIN] = zigbee_device + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, close_serial_port) + zigbee_device.add_frame_rx_handler(_frame_received) return True -def close_serial_port(*args): - """Close the serial port we're using to communicate with the Zigbee.""" - DEVICE.zb.serial.close() - - def frame_is_relevant(entity, frame): """Test whether the frame is relevant to the entity.""" if frame.get("source_addr_long") != entity.config.address: @@ -229,13 +199,13 @@ class ZigBeeDigitalOutConfig(ZigBeePinConfig): """ if self._config.get("on_state", "").lower() == "low": bool2state = { - True: GPIO_DIGITAL_OUTPUT_LOW, - False: GPIO_DIGITAL_OUTPUT_HIGH, + True: xb_const.GPIO_DIGITAL_OUTPUT_LOW, + False: xb_const.GPIO_DIGITAL_OUTPUT_HIGH, } else: bool2state = { - True: GPIO_DIGITAL_OUTPUT_HIGH, - False: GPIO_DIGITAL_OUTPUT_LOW, + True: xb_const.GPIO_DIGITAL_OUTPUT_HIGH, + False: xb_const.GPIO_DIGITAL_OUTPUT_LOW, } state2bool = {v: k for k, v in bool2state.items()} return bool2state, state2bool @@ -269,9 +239,10 @@ class ZigBeeAnalogInConfig(ZigBeePinConfig): class ZigBeeDigitalIn(Entity): """Representation of a GPIO pin configured as a digital input.""" - def __init__(self, hass, config): + def __init__(self, config, device): """Initialize the device.""" self._config = config + self._device = device self._state = False async def async_added_to_hass(self): @@ -286,7 +257,7 @@ class ZigBeeDigitalIn(Entity): if not frame_is_relevant(self, frame): return sample = next(iter(frame["samples"])) - pin_name = DIGITAL_PINS[self._config.pin] + pin_name = xb_const.DIGITAL_PINS[self._config.pin] if pin_name not in sample: # Doesn't contain information about our pin return @@ -322,18 +293,18 @@ class ZigBeeDigitalIn(Entity): def update(self): """Ask the Zigbee device what state its input pin is in.""" try: - sample = DEVICE.get_sample(self._config.address) - except ZIGBEE_TX_FAILURE: + sample = self._device.get_sample(self._config.address) + except ZigBeeTxFailure: _LOGGER.warning( "Transmission failure when attempting to get sample from " "Zigbee device at address: %s", hexlify(self._config.address), ) return - except ZIGBEE_EXCEPTION as exc: + except ZigBeeException as exc: _LOGGER.exception("Unable to get sample from Zigbee device: %s", exc) return - pin_name = DIGITAL_PINS[self._config.pin] + pin_name = xb_const.DIGITAL_PINS[self._config.pin] if pin_name not in sample: _LOGGER.warning( "Pin %s (%s) was not in the sample provided by Zigbee device %s.", @@ -351,17 +322,17 @@ class ZigBeeDigitalOut(ZigBeeDigitalIn): def _set_state(self, state): """Initialize the Zigbee digital out device.""" try: - DEVICE.set_gpio_pin( + self._device.set_gpio_pin( self._config.pin, self._config.bool2state[state], self._config.address ) - except ZIGBEE_TX_FAILURE: + except ZigBeeTxFailure: _LOGGER.warning( "Transmission failure when attempting to set output pin on " "Zigbee device at address: %s", hexlify(self._config.address), ) return - except ZIGBEE_EXCEPTION as exc: + except ZigBeeException as exc: _LOGGER.exception("Unable to set digital pin on Zigbee device: %s", exc) return self._state = state @@ -379,15 +350,17 @@ class ZigBeeDigitalOut(ZigBeeDigitalIn): def update(self): """Ask the Zigbee device what its output is set to.""" try: - pin_state = DEVICE.get_gpio_pin(self._config.pin, self._config.address) - except ZIGBEE_TX_FAILURE: + pin_state = self._device.get_gpio_pin( + self._config.pin, self._config.address + ) + except ZigBeeTxFailure: _LOGGER.warning( "Transmission failure when attempting to get output pin status" " from Zigbee device at address: %s", hexlify(self._config.address), ) return - except ZIGBEE_EXCEPTION as exc: + except ZigBeeException as exc: _LOGGER.exception( "Unable to get output pin status from Zigbee device: %s", exc ) @@ -398,9 +371,10 @@ class ZigBeeDigitalOut(ZigBeeDigitalIn): class ZigBeeAnalogIn(Entity): """Representation of a GPIO pin configured as an analog input.""" - def __init__(self, hass, config): + def __init__(self, config, device): """Initialize the ZigBee analog in device.""" self._config = config + self._device = device self._value = None async def async_added_to_hass(self): @@ -415,12 +389,12 @@ class ZigBeeAnalogIn(Entity): if not frame_is_relevant(self, frame): return sample = frame["samples"].pop() - pin_name = ANALOG_PINS[self._config.pin] + pin_name = xb_const.ANALOG_PINS[self._config.pin] if pin_name not in sample: # Doesn't contain information about our pin return - self._value = CONVERT_ADC( - sample[pin_name], ADC_PERCENTAGE, self._config.max_voltage + self._value = convert_adc( + sample[pin_name], xb_const.ADC_PERCENTAGE, self._config.max_voltage ) self.schedule_update_ha_state() @@ -454,17 +428,17 @@ class ZigBeeAnalogIn(Entity): def update(self): """Get the latest reading from the ADC.""" try: - self._value = DEVICE.read_analog_pin( + self._value = self._device.read_analog_pin( self._config.pin, self._config.max_voltage, self._config.address, - ADC_PERCENTAGE, + xb_const.ADC_PERCENTAGE, ) - except ZIGBEE_TX_FAILURE: + except ZigBeeTxFailure: _LOGGER.warning( "Transmission failure when attempting to get sample from " "Zigbee device at address: %s", hexlify(self._config.address), ) - except ZIGBEE_EXCEPTION as exc: + except ZigBeeException as exc: _LOGGER.exception("Unable to get sample from Zigbee device: %s", exc) diff --git a/homeassistant/components/zigbee/binary_sensor.py b/homeassistant/components/zigbee/binary_sensor.py index 8b37107b906..d32554e5744 100644 --- a/homeassistant/components/zigbee/binary_sensor.py +++ b/homeassistant/components/zigbee/binary_sensor.py @@ -3,7 +3,7 @@ import voluptuous as vol from homeassistant.components.binary_sensor import BinarySensorDevice -from . import PLATFORM_SCHEMA, ZigBeeDigitalIn, ZigBeeDigitalInConfig +from . import DOMAIN, PLATFORM_SCHEMA, ZigBeeDigitalIn, ZigBeeDigitalInConfig CONF_ON_STATE = "on_state" @@ -15,7 +15,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({vol.Optional(CONF_ON_STATE): vol.In(ST def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the Zigbee binary sensor platform.""" - add_entities([ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))], True) + zigbee_device = hass.data[DOMAIN] + add_entities( + [ZigBeeBinarySensor(ZigBeeDigitalInConfig(config), zigbee_device)], True + ) class ZigBeeBinarySensor(ZigBeeDigitalIn, BinarySensorDevice): diff --git a/homeassistant/components/zigbee/light.py b/homeassistant/components/zigbee/light.py index 86994a55446..54f6044c3dd 100644 --- a/homeassistant/components/zigbee/light.py +++ b/homeassistant/components/zigbee/light.py @@ -3,7 +3,7 @@ import voluptuous as vol from homeassistant.components.light import Light -from . import PLATFORM_SCHEMA, ZigBeeDigitalOut, ZigBeeDigitalOutConfig +from . import DOMAIN, PLATFORM_SCHEMA, ZigBeeDigitalOut, ZigBeeDigitalOutConfig CONF_ON_STATE = "on_state" @@ -17,7 +17,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( def setup_platform(hass, config, add_entities, discovery_info=None): """Create and add an entity based on the configuration.""" - add_entities([ZigBeeLight(hass, ZigBeeDigitalOutConfig(config))]) + zigbee_device = hass.data[DOMAIN] + add_entities([ZigBeeLight(ZigBeeDigitalOutConfig(config), zigbee_device)]) class ZigBeeLight(ZigBeeDigitalOut, Light): diff --git a/homeassistant/components/zigbee/sensor.py b/homeassistant/components/zigbee/sensor.py index 648b3bd5a2f..0c709a6d1a5 100644 --- a/homeassistant/components/zigbee/sensor.py +++ b/homeassistant/components/zigbee/sensor.py @@ -3,12 +3,18 @@ from binascii import hexlify import logging import voluptuous as vol +from xbee_helper.exceptions import ZigBeeException, ZigBeeTxFailure -from homeassistant.components import zigbee from homeassistant.const import TEMP_CELSIUS from homeassistant.helpers.entity import Entity -from . import PLATFORM_SCHEMA +from . import ( + DOMAIN, + PLATFORM_SCHEMA, + ZigBeeAnalogIn, + ZigBeeAnalogInConfig, + ZigBeeConfig, +) _LOGGER = logging.getLogger(__name__) @@ -32,6 +38,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): Uses the 'type' config value to work out which type of Zigbee sensor we're dealing with and instantiates the relevant classes to handle it. """ + zigbee_device = hass.data[DOMAIN] typ = config.get(CONF_TYPE) try: @@ -40,15 +47,16 @@ def setup_platform(hass, config, add_entities, discovery_info=None): _LOGGER.exception("Unknown Zigbee sensor type: %s", typ) return - add_entities([sensor_class(hass, config_class(config))], True) + add_entities([sensor_class(config_class(config), zigbee_device)], True) class ZigBeeTemperatureSensor(Entity): """Representation of XBee Pro temperature sensor.""" - def __init__(self, hass, config): + def __init__(self, config, device): """Initialize the sensor.""" self._config = config + self._device = device self._temp = None @property @@ -69,19 +77,19 @@ class ZigBeeTemperatureSensor(Entity): def update(self): """Get the latest data.""" try: - self._temp = zigbee.DEVICE.get_temperature(self._config.address) - except zigbee.ZIGBEE_TX_FAILURE: + self._temp = self._device.get_temperature(self._config.address) + except ZigBeeTxFailure: _LOGGER.warning( "Transmission failure when attempting to get sample from " "Zigbee device at address: %s", hexlify(self._config.address), ) - except zigbee.ZIGBEE_EXCEPTION as exc: + except ZigBeeException as exc: _LOGGER.exception("Unable to get sample from Zigbee device: %s", exc) # This must be below the classes to which it refers. TYPE_CLASSES = { - "temperature": (ZigBeeTemperatureSensor, zigbee.ZigBeeConfig), - "analog": (zigbee.ZigBeeAnalogIn, zigbee.ZigBeeAnalogInConfig), + "temperature": (ZigBeeTemperatureSensor, ZigBeeConfig), + "analog": (ZigBeeAnalogIn, ZigBeeAnalogInConfig), } diff --git a/homeassistant/components/zigbee/switch.py b/homeassistant/components/zigbee/switch.py index 71e419e410f..e29d2c045df 100644 --- a/homeassistant/components/zigbee/switch.py +++ b/homeassistant/components/zigbee/switch.py @@ -3,7 +3,7 @@ import voluptuous as vol from homeassistant.components.switch import SwitchDevice -from . import PLATFORM_SCHEMA, ZigBeeDigitalOut, ZigBeeDigitalOutConfig +from . import DOMAIN, PLATFORM_SCHEMA, ZigBeeDigitalOut, ZigBeeDigitalOutConfig CONF_ON_STATE = "on_state" @@ -16,7 +16,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({vol.Optional(CONF_ON_STATE): vol.In(ST def setup_platform(hass, config, add_entities, discovery_info=None): """Set up the Zigbee switch platform.""" - add_entities([ZigBeeSwitch(hass, ZigBeeDigitalOutConfig(config))]) + zigbee_device = hass.data[DOMAIN] + add_entities([ZigBeeSwitch(ZigBeeDigitalOutConfig(config), zigbee_device)]) class ZigBeeSwitch(ZigBeeDigitalOut, SwitchDevice):