diff --git a/homeassistant/components/binary_sensor/knx.py b/homeassistant/components/binary_sensor/knx.py index e6b28047cb8..76142dc0af2 100644 --- a/homeassistant/components/binary_sensor/knx.py +++ b/homeassistant/components/binary_sensor/knx.py @@ -105,7 +105,7 @@ class KNXBinarySensor(BinarySensorDevice): def __init__(self, hass, device): """Initialize of KNX binary sensor.""" - self.device = device + self._device = device self.hass = hass self.async_register_callbacks() self.automations = [] @@ -116,12 +116,12 @@ class KNXBinarySensor(BinarySensorDevice): async def after_update_callback(device): """Call after device was updated.""" await self.async_update_ha_state() - self.device.register_device_updated_cb(after_update_callback) + self._device.register_device_updated_cb(after_update_callback) @property def name(self): """Return the name of the KNX device.""" - return self.device.name + return self._device.name @property def available(self): @@ -136,9 +136,9 @@ class KNXBinarySensor(BinarySensorDevice): @property def device_class(self): """Return the class of this sensor.""" - return self.device.device_class + return self._device.device_class @property def is_on(self): """Return true if the binary sensor is on.""" - return self.device.is_on() + return self._device.is_on() diff --git a/homeassistant/components/binary_sensor/nest.py b/homeassistant/components/binary_sensor/nest.py index 31460c1eedc..03bc484983b 100644 --- a/homeassistant/components/binary_sensor/nest.py +++ b/homeassistant/components/binary_sensor/nest.py @@ -130,7 +130,7 @@ class NestBinarySensor(NestSensorDevice, BinarySensorDevice): def update(self): """Retrieve latest state.""" - value = getattr(self.device, self.variable) + value = getattr(self._device, self.variable) if self.variable in STRUCTURE_BINARY_TYPES: self._state = bool(STRUCTURE_BINARY_STATE_MAP [self.variable].get(value)) @@ -154,4 +154,5 @@ class NestActivityZoneSensor(NestBinarySensor): def update(self): """Retrieve latest state.""" - self._state = self.device.has_ongoing_motion_in_zone(self.zone.zone_id) + self._state = self._device.has_ongoing_motion_in_zone( + self.zone.zone_id) diff --git a/homeassistant/components/binary_sensor/tellduslive.py b/homeassistant/components/binary_sensor/tellduslive.py index e5d2d83fe47..6746d532780 100644 --- a/homeassistant/components/binary_sensor/tellduslive.py +++ b/homeassistant/components/binary_sensor/tellduslive.py @@ -31,4 +31,4 @@ class TelldusLiveSensor(TelldusLiveEntity, BinarySensorDevice): @property def is_on(self): """Return true if switch is on.""" - return self.device.is_on + return self._device.is_on diff --git a/homeassistant/components/camera/nest.py b/homeassistant/components/camera/nest.py index bf6700371fd..3f09bc9ee1c 100644 --- a/homeassistant/components/camera/nest.py +++ b/homeassistant/components/camera/nest.py @@ -46,7 +46,7 @@ class NestCamera(Camera): """Initialize a Nest Camera.""" super(NestCamera, self).__init__() self.structure = structure - self.device = device + self._device = device self._location = None self._name = None self._online = None @@ -93,7 +93,7 @@ class NestCamera(Camera): # Calling Nest API in is_streaming setter. # device.is_streaming would not immediately change until the process # finished in Nest Cam. - self.device.is_streaming = False + self._device.is_streaming = False def turn_on(self): """Turn on camera.""" @@ -105,15 +105,15 @@ class NestCamera(Camera): # Calling Nest API in is_streaming setter. # device.is_streaming would not immediately change until the process # finished in Nest Cam. - self.device.is_streaming = True + self._device.is_streaming = True def update(self): """Cache value from Python-nest.""" - self._location = self.device.where - self._name = self.device.name - self._online = self.device.online - self._is_streaming = self.device.is_streaming - self._is_video_history_enabled = self.device.is_video_history_enabled + self._location = self._device.where + self._name = self._device.name + self._online = self._device.online + self._is_streaming = self._device.is_streaming + self._is_video_history_enabled = self._device.is_video_history_enabled if self._is_video_history_enabled: # NestAware allowed 10/min @@ -130,7 +130,7 @@ class NestCamera(Camera): """Return a still image response from the camera.""" now = utcnow() if self._ready_for_snapshot(now): - url = self.device.snapshot_url + url = self._device.snapshot_url try: response = requests.get(url) diff --git a/homeassistant/components/climate/heatmiser.py b/homeassistant/components/climate/heatmiser.py index 12057e88647..116545afc15 100644 --- a/homeassistant/components/climate/heatmiser.py +++ b/homeassistant/components/climate/heatmiser.py @@ -58,7 +58,6 @@ class HeatmiserV3Thermostat(ClimateDevice): def __init__(self, heatmiser, device, name, serport): """Initialize the thermostat.""" self.heatmiser = heatmiser - self.device = device self.serport = serport self._current_temperature = None self._name = name diff --git a/homeassistant/components/climate/knx.py b/homeassistant/components/climate/knx.py index 1f95a8cb43d..a9d26288433 100644 --- a/homeassistant/components/climate/knx.py +++ b/homeassistant/components/climate/knx.py @@ -118,7 +118,7 @@ class KNXClimate(ClimateDevice): def __init__(self, hass, device): """Initialize of a KNX climate device.""" - self.device = device + self._device = device self.hass = hass self.async_register_callbacks() @@ -126,7 +126,7 @@ class KNXClimate(ClimateDevice): def supported_features(self): """Return the list of supported features.""" support = SUPPORT_TARGET_TEMPERATURE - if self.device.supports_operation_mode: + if self._device.supports_operation_mode: support |= SUPPORT_OPERATION_MODE return support @@ -135,12 +135,12 @@ class KNXClimate(ClimateDevice): async def after_update_callback(device): """Call after device was updated.""" await self.async_update_ha_state() - self.device.register_device_updated_cb(after_update_callback) + self._device.register_device_updated_cb(after_update_callback) @property def name(self): """Return the name of the KNX device.""" - return self.device.name + return self._device.name @property def available(self): @@ -160,41 +160,41 @@ class KNXClimate(ClimateDevice): @property def current_temperature(self): """Return the current temperature.""" - return self.device.temperature.value + return self._device.temperature.value @property def target_temperature_step(self): """Return the supported step of target temperature.""" - return self.device.setpoint_shift_step + return self._device.setpoint_shift_step @property def target_temperature(self): """Return the temperature we try to reach.""" - return self.device.target_temperature.value + return self._device.target_temperature.value @property def min_temp(self): """Return the minimum temperature.""" - return self.device.target_temperature_min + return self._device.target_temperature_min @property def max_temp(self): """Return the maximum temperature.""" - return self.device.target_temperature_max + return self._device.target_temperature_max async def async_set_temperature(self, **kwargs): """Set new target temperature.""" temperature = kwargs.get(ATTR_TEMPERATURE) if temperature is None: return - await self.device.set_target_temperature(temperature) + await self._device.set_target_temperature(temperature) await self.async_update_ha_state() @property def current_operation(self): """Return current operation ie. heat, cool, idle.""" - if self.device.supports_operation_mode: - return self.device.operation_mode.value + if self._device.supports_operation_mode: + return self._device.operation_mode.value return None @property @@ -202,11 +202,11 @@ class KNXClimate(ClimateDevice): """Return the list of available operation modes.""" return [operation_mode.value for operation_mode in - self.device.get_supported_operation_modes()] + self._device.get_supported_operation_modes()] async def async_set_operation_mode(self, operation_mode): """Set operation mode.""" - if self.device.supports_operation_mode: + if self._device.supports_operation_mode: from xknx.knx import HVACOperationMode knx_operation_mode = HVACOperationMode(operation_mode) - await self.device.set_operation_mode(knx_operation_mode) + await self._device.set_operation_mode(knx_operation_mode) diff --git a/homeassistant/components/climate/nest.py b/homeassistant/components/climate/nest.py index fa3943c3e27..2fdb11866e0 100644 --- a/homeassistant/components/climate/nest.py +++ b/homeassistant/components/climate/nest.py @@ -57,7 +57,7 @@ class NestThermostat(ClimateDevice): """Initialize the thermostat.""" self._unit = temp_unit self.structure = structure - self.device = device + self._device = device self._fan_list = [STATE_ON, STATE_AUTO] # Set the default supported features @@ -68,13 +68,13 @@ class NestThermostat(ClimateDevice): self._operation_list = [STATE_OFF] # Add supported nest thermostat features - if self.device.can_heat: + if self._device.can_heat: self._operation_list.append(STATE_HEAT) - if self.device.can_cool: + if self._device.can_cool: self._operation_list.append(STATE_COOL) - if self.device.can_heat and self.device.can_cool: + if self._device.can_heat and self._device.can_cool: self._operation_list.append(STATE_AUTO) self._support_flags = (self._support_flags | SUPPORT_TARGET_TEMPERATURE_HIGH | @@ -83,7 +83,7 @@ class NestThermostat(ClimateDevice): self._operation_list.append(STATE_ECO) # feature of device - self._has_fan = self.device.has_fan + self._has_fan = self._device.has_fan if self._has_fan: self._support_flags = (self._support_flags | SUPPORT_FAN_MODE) @@ -125,7 +125,7 @@ class NestThermostat(ClimateDevice): @property def unique_id(self): """Unique ID for this device.""" - return self.device.serial + return self._device.serial @property def name(self): @@ -202,7 +202,7 @@ class NestThermostat(ClimateDevice): _LOGGER.debug("Nest set_temperature-output-value=%s", temp) try: if temp is not None: - self.device.target = temp + self._device.target = temp except nest.nest.APIError as api_error: _LOGGER.error("An error occurred while setting temperature: %s", api_error) @@ -220,7 +220,7 @@ class NestThermostat(ClimateDevice): _LOGGER.error( "An error occurred while setting device mode. " "Invalid operation mode: %s", operation_mode) - self.device.mode = device_mode + self._device.mode = device_mode @property def operation_list(self): @@ -254,7 +254,7 @@ class NestThermostat(ClimateDevice): def set_fan_mode(self, fan_mode): """Turn fan on/off.""" if self._has_fan: - self.device.fan = fan_mode.lower() + self._device.fan = fan_mode.lower() @property def min_temp(self): @@ -268,20 +268,20 @@ class NestThermostat(ClimateDevice): def update(self): """Cache value from Python-nest.""" - self._location = self.device.where - self._name = self.device.name - self._humidity = self.device.humidity - self._temperature = self.device.temperature - self._mode = self.device.mode - self._target_temperature = self.device.target - self._fan = self.device.fan + self._location = self._device.where + self._name = self._device.name + self._humidity = self._device.humidity + self._temperature = self._device.temperature + self._mode = self._device.mode + self._target_temperature = self._device.target + self._fan = self._device.fan self._away = self.structure.away == 'away' - self._eco_temperature = self.device.eco_temperature - self._locked_temperature = self.device.locked_temperature - self._min_temperature = self.device.min_temperature - self._max_temperature = self.device.max_temperature - self._is_locked = self.device.is_locked - if self.device.temperature_scale == 'C': + self._eco_temperature = self._device.eco_temperature + self._locked_temperature = self._device.locked_temperature + self._min_temperature = self._device.min_temperature + self._max_temperature = self._device.max_temperature + self._is_locked = self._device.is_locked + if self._device.temperature_scale == 'C': self._temperature_scale = TEMP_CELSIUS else: self._temperature_scale = TEMP_FAHRENHEIT diff --git a/homeassistant/components/climate/radiotherm.py b/homeassistant/components/climate/radiotherm.py index c8441a9f7af..d158eb52a9d 100644 --- a/homeassistant/components/climate/radiotherm.py +++ b/homeassistant/components/climate/radiotherm.py @@ -120,7 +120,7 @@ class RadioThermostat(ClimateDevice): def __init__(self, device, hold_temp, away_temps): """Initialize the thermostat.""" - self.device = device + self._device = device self._target_temperature = None self._current_temperature = None self._current_operation = STATE_IDLE @@ -137,8 +137,8 @@ class RadioThermostat(ClimateDevice): # Fan circulate mode is only supported by the CT80 models. import radiotherm - self._is_model_ct80 = isinstance(self.device, - radiotherm.thermostat.CT80) + self._is_model_ct80 = isinstance( + self._device, radiotherm.thermostat.CT80) @property def supported_features(self): @@ -194,7 +194,7 @@ class RadioThermostat(ClimateDevice): """Turn fan on/off.""" code = FAN_MODE_TO_CODE.get(fan_mode, None) if code is not None: - self.device.fmode = code + self._device.fmode = code @property def current_temperature(self): @@ -234,15 +234,15 @@ class RadioThermostat(ClimateDevice): # First time - get the name from the thermostat. This is # normally set in the radio thermostat web app. if self._name is None: - self._name = self.device.name['raw'] + self._name = self._device.name['raw'] # Request the current state from the thermostat. - data = self.device.tstat['raw'] + data = self._device.tstat['raw'] current_temp = data['temp'] if current_temp == -1: _LOGGER.error('%s (%s) was busy (temp == -1)', self._name, - self.device.host) + self._device.host) return # Map thermostat values into various STATE_ flags. @@ -277,30 +277,30 @@ class RadioThermostat(ClimateDevice): temperature = round_temp(temperature) if self._current_operation == STATE_COOL: - self.device.t_cool = temperature + self._device.t_cool = temperature elif self._current_operation == STATE_HEAT: - self.device.t_heat = temperature + self._device.t_heat = temperature elif self._current_operation == STATE_AUTO: if self._tstate == STATE_COOL: - self.device.t_cool = temperature + self._device.t_cool = temperature elif self._tstate == STATE_HEAT: - self.device.t_heat = temperature + self._device.t_heat = temperature # Only change the hold if requested or if hold mode was turned # on and we haven't set it yet. if kwargs.get('hold_changed', False) or not self._hold_set: if self._hold_temp or self._away: - self.device.hold = 1 + self._device.hold = 1 self._hold_set = True else: - self.device.hold = 0 + self._device.hold = 0 def set_time(self): """Set device time.""" # Calling this clears any local temperature override and # reverts to the scheduled temperature. now = datetime.datetime.now() - self.device.time = { + self._device.time = { 'day': now.weekday(), 'hour': now.hour, 'minute': now.minute @@ -309,13 +309,13 @@ class RadioThermostat(ClimateDevice): def set_operation_mode(self, operation_mode): """Set operation mode (auto, cool, heat, off).""" if operation_mode in (STATE_OFF, STATE_AUTO): - self.device.tmode = TEMP_MODE_TO_CODE[operation_mode] + self._device.tmode = TEMP_MODE_TO_CODE[operation_mode] # Setting t_cool or t_heat automatically changes tmode. elif operation_mode == STATE_COOL: - self.device.t_cool = self._target_temperature + self._device.t_cool = self._target_temperature elif operation_mode == STATE_HEAT: - self.device.t_heat = self._target_temperature + self._device.t_heat = self._target_temperature def turn_away_mode_on(self): """Turn away on. diff --git a/homeassistant/components/cover/knx.py b/homeassistant/components/cover/knx.py index 7bb20e4cf1f..59195d73a2f 100644 --- a/homeassistant/components/cover/knx.py +++ b/homeassistant/components/cover/knx.py @@ -96,7 +96,7 @@ class KNXCover(CoverDevice): def __init__(self, hass, device): """Initialize the cover.""" - self.device = device + self._device = device self.hass = hass self.async_register_callbacks() @@ -108,12 +108,12 @@ class KNXCover(CoverDevice): async def after_update_callback(device): """Call after device was updated.""" await self.async_update_ha_state() - self.device.register_device_updated_cb(after_update_callback) + self._device.register_device_updated_cb(after_update_callback) @property def name(self): """Return the name of the KNX device.""" - return self.device.name + return self._device.name @property def available(self): @@ -130,56 +130,56 @@ class KNXCover(CoverDevice): """Flag supported features.""" supported_features = SUPPORT_OPEN | SUPPORT_CLOSE | \ SUPPORT_SET_POSITION | SUPPORT_STOP - if self.device.supports_angle: + if self._device.supports_angle: supported_features |= SUPPORT_SET_TILT_POSITION return supported_features @property def current_cover_position(self): """Return the current position of the cover.""" - return self.device.current_position() + return self._device.current_position() @property def is_closed(self): """Return if the cover is closed.""" - return self.device.is_closed() + return self._device.is_closed() async def async_close_cover(self, **kwargs): """Close the cover.""" - if not self.device.is_closed(): - await self.device.set_down() + if not self._device.is_closed(): + await self._device.set_down() self.start_auto_updater() async def async_open_cover(self, **kwargs): """Open the cover.""" - if not self.device.is_open(): - await self.device.set_up() + if not self._device.is_open(): + await self._device.set_up() self.start_auto_updater() async def async_set_cover_position(self, **kwargs): """Move the cover to a specific position.""" if ATTR_POSITION in kwargs: position = kwargs[ATTR_POSITION] - await self.device.set_position(position) + await self._device.set_position(position) self.start_auto_updater() async def async_stop_cover(self, **kwargs): """Stop the cover.""" - await self.device.stop() + await self._device.stop() self.stop_auto_updater() @property def current_cover_tilt_position(self): """Return current tilt position of cover.""" - if not self.device.supports_angle: + if not self._device.supports_angle: return None - return self.device.current_angle() + return self._device.current_angle() async def async_set_cover_tilt_position(self, **kwargs): """Move the cover tilt to a specific position.""" if ATTR_TILT_POSITION in kwargs: tilt_position = kwargs[ATTR_TILT_POSITION] - await self.device.set_angle(tilt_position) + await self._device.set_angle(tilt_position) def start_auto_updater(self): """Start the autoupdater to update HASS while cover is moving.""" @@ -197,7 +197,7 @@ class KNXCover(CoverDevice): def auto_updater_hook(self, now): """Call for the autoupdater.""" self.async_schedule_update_ha_state() - if self.device.position_reached(): + if self._device.position_reached(): self.stop_auto_updater() - self.hass.add_job(self.device.auto_stop_if_necessary()) + self.hass.add_job(self._device.auto_stop_if_necessary()) diff --git a/homeassistant/components/cover/tellduslive.py b/homeassistant/components/cover/tellduslive.py index 4a78cb96d06..b4bde037a12 100644 --- a/homeassistant/components/cover/tellduslive.py +++ b/homeassistant/components/cover/tellduslive.py @@ -28,19 +28,19 @@ class TelldusLiveCover(TelldusLiveEntity, CoverDevice): @property def is_closed(self): """Return the current position of the cover.""" - return self.device.is_down + return self._device.is_down def close_cover(self, **kwargs): """Close the cover.""" - self.device.down() + self._device.down() self.changed() def open_cover(self, **kwargs): """Open the cover.""" - self.device.up() + self._device.up() self.changed() def stop_cover(self, **kwargs): """Stop the cover.""" - self.device.stop() + self._device.stop() self.changed() diff --git a/homeassistant/components/juicenet.py b/homeassistant/components/juicenet.py index 55567d45879..2ed32521f1d 100644 --- a/homeassistant/components/juicenet.py +++ b/homeassistant/components/juicenet.py @@ -46,29 +46,29 @@ class JuicenetDevice(Entity): def __init__(self, device, sensor_type, hass): """Initialise the sensor.""" self.hass = hass - self.device = device + self._device = device self.type = sensor_type @property def name(self): """Return the name of the device.""" - return self.device.name() + return self._device.name() def update(self): """Update state of the device.""" - self.device.update_state() + self._device.update_state() @property def _manufacturer_device_id(self): """Return the manufacturer device id.""" - return self.device.id() + return self._device.id() @property def _token(self): """Return the device API token.""" - return self.device.token() + return self._device.token() @property def unique_id(self): """Return a unique ID.""" - return "{}-{}".format(self.device.id(), self.type) + return "{}-{}".format(self._device.id(), self.type) diff --git a/homeassistant/components/light/knx.py b/homeassistant/components/light/knx.py index 8fa2b56d1d2..ee8389fbb71 100644 --- a/homeassistant/components/light/knx.py +++ b/homeassistant/components/light/knx.py @@ -79,7 +79,7 @@ class KNXLight(Light): def __init__(self, hass, device): """Initialize of KNX light.""" - self.device = device + self._device = device self.hass = hass self.async_register_callbacks() @@ -89,12 +89,12 @@ class KNXLight(Light): async def after_update_callback(device): """Call after device was updated.""" await self.async_update_ha_state() - self.device.register_device_updated_cb(after_update_callback) + self._device.register_device_updated_cb(after_update_callback) @property def name(self): """Return the name of the KNX device.""" - return self.device.name + return self._device.name @property def available(self): @@ -109,15 +109,15 @@ class KNXLight(Light): @property def brightness(self): """Return the brightness of this light between 0..255.""" - return self.device.current_brightness \ - if self.device.supports_brightness else \ + return self._device.current_brightness \ + if self._device.supports_brightness else \ None @property def hs_color(self): """Return the HS color value.""" - if self.device.supports_color: - return color_util.color_RGB_to_hs(*self.device.current_color) + if self._device.supports_color: + return color_util.color_RGB_to_hs(*self._device.current_color) return None @property @@ -143,30 +143,30 @@ class KNXLight(Light): @property def is_on(self): """Return true if light is on.""" - return self.device.state + return self._device.state @property def supported_features(self): """Flag supported features.""" flags = 0 - if self.device.supports_brightness: + if self._device.supports_brightness: flags |= SUPPORT_BRIGHTNESS - if self.device.supports_color: + if self._device.supports_color: flags |= SUPPORT_COLOR return flags async def async_turn_on(self, **kwargs): """Turn the light on.""" if ATTR_BRIGHTNESS in kwargs: - if self.device.supports_brightness: - await self.device.set_brightness(int(kwargs[ATTR_BRIGHTNESS])) + if self._device.supports_brightness: + await self._device.set_brightness(int(kwargs[ATTR_BRIGHTNESS])) elif ATTR_HS_COLOR in kwargs: - if self.device.supports_color: - await self.device.set_color(color_util.color_hs_to_RGB( + if self._device.supports_color: + await self._device.set_color(color_util.color_hs_to_RGB( *kwargs[ATTR_HS_COLOR])) else: - await self.device.set_on() + await self._device.set_on() async def async_turn_off(self, **kwargs): """Turn the light off.""" - await self.device.set_off() + await self._device.set_off() diff --git a/homeassistant/components/light/lifx.py b/homeassistant/components/light/lifx.py index 3738fd8f004..8547d7a985d 100644 --- a/homeassistant/components/light/lifx.py +++ b/homeassistant/components/light/lifx.py @@ -389,7 +389,7 @@ class LIFXLight(Light): def __init__(self, device, effects_conductor): """Initialize the light.""" - self.device = device + self.light = device self.effects_conductor = effects_conductor self.registered = True self.postponed_update = None @@ -403,28 +403,28 @@ class LIFXLight(Light): @property def unique_id(self): """Return a unique ID.""" - return self.device.mac_addr + return self.light.mac_addr @property def name(self): """Return the name of the device.""" - return self.device.label + return self.light.label @property def who(self): """Return a string identifying the device.""" - return "%s (%s)" % (self.device.ip_addr, self.name) + return "%s (%s)" % (self.light.ip_addr, self.name) @property def min_mireds(self): """Return the coldest color_temp that this light supports.""" - kelvin = lifx_features(self.device)['max_kelvin'] + kelvin = lifx_features(self.light)['max_kelvin'] return math.floor(color_util.color_temperature_kelvin_to_mired(kelvin)) @property def max_mireds(self): """Return the warmest color_temp that this light supports.""" - kelvin = lifx_features(self.device)['min_kelvin'] + kelvin = lifx_features(self.light)['min_kelvin'] return math.ceil(color_util.color_temperature_kelvin_to_mired(kelvin)) @property @@ -432,7 +432,7 @@ class LIFXLight(Light): """Flag supported features.""" support = SUPPORT_BRIGHTNESS | SUPPORT_TRANSITION | SUPPORT_EFFECT - device_features = lifx_features(self.device) + device_features = lifx_features(self.light) if device_features['min_kelvin'] != device_features['max_kelvin']: support |= SUPPORT_COLOR_TEMP @@ -441,12 +441,12 @@ class LIFXLight(Light): @property def brightness(self): """Return the brightness of this light between 0..255.""" - return convert_16_to_8(self.device.color[2]) + return convert_16_to_8(self.light.color[2]) @property def color_temp(self): """Return the color temperature.""" - _, sat, _, kelvin = self.device.color + _, sat, _, kelvin = self.light.color if sat: return None return color_util.color_temperature_kelvin_to_mired(kelvin) @@ -454,12 +454,12 @@ class LIFXLight(Light): @property def is_on(self): """Return true if device is on.""" - return self.device.power_level != 0 + return self.light.power_level != 0 @property def effect(self): """Return the name of the currently running effect.""" - effect = self.effects_conductor.effect(self.device) + effect = self.effects_conductor.effect(self.light) if effect: return 'lifx_effect_' + effect.name return None @@ -497,7 +497,7 @@ class LIFXLight(Light): async def set_state(self, **kwargs): """Set a color on the light and turn it on/off.""" async with self.lock: - bulb = self.device + bulb = self.light await self.effects_conductor.stop([bulb]) @@ -545,12 +545,12 @@ class LIFXLight(Light): async def set_power(self, ack, pwr, duration=0): """Send a power change to the device.""" - await ack(partial(self.device.set_power, pwr, duration=duration)) + await ack(partial(self.light.set_power, pwr, duration=duration)) async def set_color(self, ack, hsbk, kwargs, duration=0): """Send a color change to the device.""" - hsbk = merge_hsbk(self.device.color, hsbk) - await ack(partial(self.device.set_color, hsbk, duration=duration)) + hsbk = merge_hsbk(self.light.color, hsbk) + await ack(partial(self.light.set_color, hsbk, duration=duration)) async def default_effect(self, **kwargs): """Start an effect with default parameters.""" @@ -563,7 +563,7 @@ class LIFXLight(Light): async def async_update(self): """Update bulb status.""" if self.available and not self.lock.locked(): - await AwaitAioLIFX().wait(self.device.get_color) + await AwaitAioLIFX().wait(self.light.get_color) class LIFXWhite(LIFXLight): @@ -600,7 +600,7 @@ class LIFXColor(LIFXLight): @property def hs_color(self): """Return the hs value.""" - hue, sat, _, _ = self.device.color + hue, sat, _, _ = self.light.color hue = hue / 65535 * 360 sat = sat / 65535 * 100 return (hue, sat) if sat else None @@ -611,7 +611,7 @@ class LIFXStrip(LIFXColor): async def set_color(self, ack, hsbk, kwargs, duration=0): """Send a color change to the device.""" - bulb = self.device + bulb = self.light num_zones = len(bulb.color_zones) zones = kwargs.get(ATTR_ZONES) @@ -659,7 +659,7 @@ class LIFXStrip(LIFXColor): while self.available and zone < top: # Each get_color_zones can update 8 zones at once resp = await AwaitAioLIFX().wait(partial( - self.device.get_color_zones, + self.light.get_color_zones, start_index=zone)) if resp: zone += 8 diff --git a/homeassistant/components/light/mochad.py b/homeassistant/components/light/mochad.py index 576e244103f..4aeb2c2c79b 100644 --- a/homeassistant/components/light/mochad.py +++ b/homeassistant/components/light/mochad.py @@ -54,8 +54,8 @@ class MochadLight(Light): self._name = dev.get(CONF_NAME, 'x10_light_dev_{}'.format(self._address)) self._comm_type = dev.get(mochad.CONF_COMM_TYPE, 'pl') - self.device = device.Device(ctrl, self._address, - comm_type=self._comm_type) + self.light = device.Device(ctrl, self._address, + comm_type=self._comm_type) self._brightness = 0 self._state = self._get_device_status() self._brightness_levels = dev.get(CONF_BRIGHTNESS_LEVELS) - 1 @@ -68,7 +68,7 @@ class MochadLight(Light): def _get_device_status(self): """Get the status of the light from mochad.""" with mochad.REQ_LOCK: - status = self.device.get_status().rstrip() + status = self.light.get_status().rstrip() return status == 'on' @property @@ -98,12 +98,12 @@ class MochadLight(Light): if self._brightness > brightness: bdelta = self._brightness - brightness mochad_brightness = self._calculate_brightness_value(bdelta) - self.device.send_cmd("dim {}".format(mochad_brightness)) + self.light.send_cmd("dim {}".format(mochad_brightness)) self._controller.read_data() elif self._brightness < brightness: bdelta = brightness - self._brightness mochad_brightness = self._calculate_brightness_value(bdelta) - self.device.send_cmd("bright {}".format(mochad_brightness)) + self.light.send_cmd("bright {}".format(mochad_brightness)) self._controller.read_data() def turn_on(self, **kwargs): @@ -112,10 +112,10 @@ class MochadLight(Light): with mochad.REQ_LOCK: if self._brightness_levels > 32: out_brightness = self._calculate_brightness_value(brightness) - self.device.send_cmd('xdim {}'.format(out_brightness)) + self.light.send_cmd('xdim {}'.format(out_brightness)) self._controller.read_data() else: - self.device.send_cmd("on") + self.light.send_cmd("on") self._controller.read_data() # There is no persistence for X10 modules so a fresh on command # will be full brightness @@ -128,7 +128,7 @@ class MochadLight(Light): def turn_off(self, **kwargs): """Send the command to turn the light on.""" with mochad.REQ_LOCK: - self.device.send_cmd('off') + self.light.send_cmd('off') self._controller.read_data() # There is no persistence for X10 modules so we need to prepare # to track a fresh on command will full brightness diff --git a/homeassistant/components/light/qwikswitch.py b/homeassistant/components/light/qwikswitch.py index 528f4f73c53..9d6e8f9169a 100644 --- a/homeassistant/components/light/qwikswitch.py +++ b/homeassistant/components/light/qwikswitch.py @@ -27,9 +27,9 @@ class QSLight(QSToggleEntity, Light): @property def brightness(self): """Return the brightness of this light (0-255).""" - return self.device.value if self.device.is_dimmer else None + return self._device.value if self._device.is_dimmer else None @property def supported_features(self): """Flag supported features.""" - return SUPPORT_BRIGHTNESS if self.device.is_dimmer else 0 + return SUPPORT_BRIGHTNESS if self._device.is_dimmer else 0 diff --git a/homeassistant/components/light/tellduslive.py b/homeassistant/components/light/tellduslive.py index 321cfd677b5..3908d43f62d 100644 --- a/homeassistant/components/light/tellduslive.py +++ b/homeassistant/components/light/tellduslive.py @@ -38,7 +38,7 @@ class TelldusLiveLight(TelldusLiveEntity, Light): @property def brightness(self): """Return the brightness of this light between 0..255.""" - return self.device.dim_level + return self._device.dim_level @property def supported_features(self): @@ -48,15 +48,15 @@ class TelldusLiveLight(TelldusLiveEntity, Light): @property def is_on(self): """Return true if light is on.""" - return self.device.is_on + return self._device.is_on def turn_on(self, **kwargs): """Turn the light on.""" brightness = kwargs.get(ATTR_BRIGHTNESS, self._last_brightness) - self.device.dim(level=brightness) + self._device.dim(level=brightness) self.changed() def turn_off(self, **kwargs): """Turn the light off.""" - self.device.turn_off() + self._device.turn_off() self.changed() diff --git a/homeassistant/components/light/wemo.py b/homeassistant/components/light/wemo.py index 78dedb12718..f07865473d1 100644 --- a/homeassistant/components/light/wemo.py +++ b/homeassistant/components/light/wemo.py @@ -76,39 +76,39 @@ class WemoLight(Light): def __init__(self, device, update_lights): """Initialize the WeMo light.""" self.light_id = device.name - self.device = device + self.wemo = device self.update_lights = update_lights @property def unique_id(self): """Return the ID of this light.""" - return self.device.uniqueID + return self.wemo.uniqueID @property def name(self): """Return the name of the light.""" - return self.device.name + return self.wemo.name @property def brightness(self): """Return the brightness of this light between 0..255.""" - return self.device.state.get('level', 255) + return self.wemo.state.get('level', 255) @property def hs_color(self): """Return the hs color values of this light.""" - xy_color = self.device.state.get('color_xy') + xy_color = self.wemo.state.get('color_xy') return color_util.color_xy_to_hs(*xy_color) if xy_color else None @property def color_temp(self): """Return the color temperature of this light in mireds.""" - return self.device.state.get('temperature_mireds') + return self.wemo.state.get('temperature_mireds') @property def is_on(self): """Return true if device is on.""" - return self.device.state['onoff'] != 0 + return self.wemo.state['onoff'] != 0 @property def supported_features(self): @@ -118,7 +118,7 @@ class WemoLight(Light): @property def available(self): """Return if light is available.""" - return self.device.state['available'] + return self.wemo.state['available'] def turn_on(self, **kwargs): """Turn the light on.""" @@ -128,23 +128,23 @@ class WemoLight(Light): if hs_color is not None: xy_color = color_util.color_hs_to_xy(*hs_color) - self.device.set_color(xy_color, transition=transitiontime) + self.wemo.set_color(xy_color, transition=transitiontime) if ATTR_COLOR_TEMP in kwargs: colortemp = kwargs[ATTR_COLOR_TEMP] - self.device.set_temperature(mireds=colortemp, - transition=transitiontime) + self.wemo.set_temperature(mireds=colortemp, + transition=transitiontime) if ATTR_BRIGHTNESS in kwargs: brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness or 255) - self.device.turn_on(level=brightness, transition=transitiontime) + self.wemo.turn_on(level=brightness, transition=transitiontime) else: - self.device.turn_on(transition=transitiontime) + self.wemo.turn_on(transition=transitiontime) def turn_off(self, **kwargs): """Turn the light off.""" transitiontime = int(kwargs.get(ATTR_TRANSITION, 0)) - self.device.turn_off(transition=transitiontime) + self.wemo.turn_off(transition=transitiontime) def update(self): """Synchronize state with bridge.""" diff --git a/homeassistant/components/media_player/emby.py b/homeassistant/components/media_player/emby.py index 1dfb19a33be..8dd4ebcb120 100644 --- a/homeassistant/components/media_player/emby.py +++ b/homeassistant/components/media_player/emby.py @@ -132,7 +132,7 @@ class EmbyDevice(MediaPlayerDevice): _LOGGER.debug("New Emby Device initialized with ID: %s", device_id) self.emby = emby self.device_id = device_id - self.device = self.emby.devices[self.device_id] + self._device = self.emby.devices[self.device_id] self._hidden = False self._available = True @@ -150,11 +150,11 @@ class EmbyDevice(MediaPlayerDevice): def async_update_callback(self, msg): """Handle device updates.""" # Check if we should update progress - if self.device.media_position: - if self.device.media_position != self.media_status_last_position: - self.media_status_last_position = self.device.media_position + if self._device.media_position: + if self._device.media_position != self.media_status_last_position: + self.media_status_last_position = self._device.media_position self.media_status_received = dt_util.utcnow() - elif not self.device.is_nowplaying: + elif not self._device.is_nowplaying: # No position, but we have an old value and are still playing self.media_status_last_position = None self.media_status_received = None @@ -187,13 +187,13 @@ class EmbyDevice(MediaPlayerDevice): @property def supports_remote_control(self): """Return control ability.""" - return self.device.supports_remote_control + return self._device.supports_remote_control @property def name(self): """Return the name of the device.""" - return 'Emby - {} - {}'.format(self.device.client, self.device.name) \ - or DEVICE_DEFAULT_NAME + return ('Emby - {} - {}'.format(self._device.client, self._device.name) + or DEVICE_DEFAULT_NAME) @property def should_poll(self): @@ -203,7 +203,7 @@ class EmbyDevice(MediaPlayerDevice): @property def state(self): """Return the state of the device.""" - state = self.device.state + state = self._device.state if state == 'Paused': return STATE_PAUSED if state == 'Playing': @@ -217,17 +217,17 @@ class EmbyDevice(MediaPlayerDevice): def app_name(self): """Return current user as app_name.""" # Ideally the media_player object would have a user property. - return self.device.username + return self._device.username @property def media_content_id(self): """Content ID of current playing media.""" - return self.device.media_id + return self._device.media_id @property def media_content_type(self): """Content type of current playing media.""" - media_type = self.device.media_type + media_type = self._device.media_type if media_type == 'Episode': return MEDIA_TYPE_TVSHOW if media_type == 'Movie': @@ -245,7 +245,7 @@ class EmbyDevice(MediaPlayerDevice): @property def media_duration(self): """Return the duration of current playing media in seconds.""" - return self.device.media_runtime + return self._device.media_runtime @property def media_position(self): @@ -264,42 +264,42 @@ class EmbyDevice(MediaPlayerDevice): @property def media_image_url(self): """Return the image URL of current playing media.""" - return self.device.media_image_url + return self._device.media_image_url @property def media_title(self): """Return the title of current playing media.""" - return self.device.media_title + return self._device.media_title @property def media_season(self): """Season of current playing media (TV Show only).""" - return self.device.media_season + return self._device.media_season @property def media_series_title(self): """Return the title of the series of current playing media (TV).""" - return self.device.media_series_title + return self._device.media_series_title @property def media_episode(self): """Return the episode of current playing media (TV only).""" - return self.device.media_episode + return self._device.media_episode @property def media_album_name(self): """Return the album name of current playing media (Music only).""" - return self.device.media_album_name + return self._device.media_album_name @property def media_artist(self): """Return the artist of current playing media (Music track only).""" - return self.device.media_artist + return self._device.media_artist @property def media_album_artist(self): """Return the album artist of current playing media (Music only).""" - return self.device.media_album_artist + return self._device.media_album_artist @property def supported_features(self): @@ -313,39 +313,39 @@ class EmbyDevice(MediaPlayerDevice): This method must be run in the event loop and returns a coroutine. """ - return self.device.media_play() + return self._device.media_play() def async_media_pause(self): """Pause the media player. This method must be run in the event loop and returns a coroutine. """ - return self.device.media_pause() + return self._device.media_pause() def async_media_stop(self): """Stop the media player. This method must be run in the event loop and returns a coroutine. """ - return self.device.media_stop() + return self._device.media_stop() def async_media_next_track(self): """Send next track command. This method must be run in the event loop and returns a coroutine. """ - return self.device.media_next() + return self._device.media_next() def async_media_previous_track(self): """Send next track command. This method must be run in the event loop and returns a coroutine. """ - return self.device.media_previous() + return self._device.media_previous() def async_media_seek(self, position): """Send seek command. This method must be run in the event loop and returns a coroutine. """ - return self.device.media_seek(position) + return self._device.media_seek(position) diff --git a/homeassistant/components/media_player/plex.py b/homeassistant/components/media_player/plex.py index e3c6f453c35..05947b3d67b 100644 --- a/homeassistant/components/media_player/plex.py +++ b/homeassistant/components/media_player/plex.py @@ -454,7 +454,7 @@ class PlexClient(MediaPlayerDevice): elif self._player_state == 'paused': self._is_player_active = True self._state = STATE_PAUSED - elif self.device: + elif self._device: self._is_player_active = False self._state = STATE_IDLE else: @@ -528,11 +528,6 @@ class PlexClient(MediaPlayerDevice): """Return the library name of playing media.""" return self._app_name - @property - def device(self): - """Return the device, if any.""" - return self._device - @property def marked_unavailable(self): """Return time device was marked unavailable.""" @@ -671,7 +666,7 @@ class PlexClient(MediaPlayerDevice): SUPPORT_TURN_OFF) # Not all devices support playback functionality # Playback includes volume, stop/play/pause, etc. - if self.device and 'playback' in self._device_protocol_capabilities: + if self._device and 'playback' in self._device_protocol_capabilities: return (SUPPORT_PAUSE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_STOP | SUPPORT_VOLUME_SET | SUPPORT_PLAY | @@ -681,22 +676,22 @@ class PlexClient(MediaPlayerDevice): def set_volume_level(self, volume): """Set volume level, range 0..1.""" - if self.device and 'playback' in self._device_protocol_capabilities: - self.device.setVolume( + if self._device and 'playback' in self._device_protocol_capabilities: + self._device.setVolume( int(volume * 100), self._active_media_plexapi_type) self._volume_level = volume # store since we can't retrieve @property def volume_level(self): """Return the volume level of the client (0..1).""" - if (self._is_player_active and self.device and + if (self._is_player_active and self._device and 'playback' in self._device_protocol_capabilities): return self._volume_level @property def is_volume_muted(self): """Return boolean if volume is currently muted.""" - if self._is_player_active and self.device: + if self._is_player_active and self._device: return self._volume_muted def mute_volume(self, mute): @@ -706,7 +701,7 @@ class PlexClient(MediaPlayerDevice): - On mute, store volume and set volume to 0 - On unmute, set volume to previously stored volume """ - if not (self.device and + if not (self._device and 'playback' in self._device_protocol_capabilities): return @@ -719,18 +714,18 @@ class PlexClient(MediaPlayerDevice): def media_play(self): """Send play command.""" - if self.device and 'playback' in self._device_protocol_capabilities: - self.device.play(self._active_media_plexapi_type) + if self._device and 'playback' in self._device_protocol_capabilities: + self._device.play(self._active_media_plexapi_type) def media_pause(self): """Send pause command.""" - if self.device and 'playback' in self._device_protocol_capabilities: - self.device.pause(self._active_media_plexapi_type) + if self._device and 'playback' in self._device_protocol_capabilities: + self._device.pause(self._active_media_plexapi_type) def media_stop(self): """Send stop command.""" - if self.device and 'playback' in self._device_protocol_capabilities: - self.device.stop(self._active_media_plexapi_type) + if self._device and 'playback' in self._device_protocol_capabilities: + self._device.stop(self._active_media_plexapi_type) def turn_off(self): """Turn the client off.""" @@ -739,17 +734,17 @@ class PlexClient(MediaPlayerDevice): def media_next_track(self): """Send next track command.""" - if self.device and 'playback' in self._device_protocol_capabilities: - self.device.skipNext(self._active_media_plexapi_type) + if self._device and 'playback' in self._device_protocol_capabilities: + self._device.skipNext(self._active_media_plexapi_type) def media_previous_track(self): """Send previous track command.""" - if self.device and 'playback' in self._device_protocol_capabilities: - self.device.skipPrevious(self._active_media_plexapi_type) + if self._device and 'playback' in self._device_protocol_capabilities: + self._device.skipPrevious(self._active_media_plexapi_type) def play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" - if not (self.device and + if not (self._device and 'playback' in self._device_protocol_capabilities): return @@ -757,7 +752,7 @@ class PlexClient(MediaPlayerDevice): media = None if media_type == 'MUSIC': - media = self.device.server.library.section( + media = self._device.server.library.section( src['library_name']).get(src['artist_name']).album( src['album_name']).get(src['track_name']) elif media_type == 'EPISODE': @@ -765,9 +760,9 @@ class PlexClient(MediaPlayerDevice): src['library_name'], src['show_name'], src['season_number'], src['episode_number']) elif media_type == 'PLAYLIST': - media = self.device.server.playlist(src['playlist_name']) + media = self._device.server.playlist(src['playlist_name']) elif media_type == 'VIDEO': - media = self.device.server.library.section( + media = self._device.server.library.section( src['library_name']).get(src['video_name']) import plexapi.playlist @@ -785,13 +780,13 @@ class PlexClient(MediaPlayerDevice): target_season = None target_episode = None - show = self.device.server.library.section(library_name).get( + show = self._device.server.library.section(library_name).get( show_name) if not season_number: playlist_name = "{} - {} Episodes".format( self.entity_id, show_name) - return self.device.server.createPlaylist( + return self._device.server.createPlaylist( playlist_name, show.episodes()) for season in show.seasons(): @@ -808,7 +803,7 @@ class PlexClient(MediaPlayerDevice): if not episode_number: playlist_name = "{} - {} Season {} Episodes".format( self.entity_id, show_name, str(season_number)) - return self.device.server.createPlaylist( + return self._device.server.createPlaylist( playlist_name, target_season.episodes()) for episode in target_season.episodes(): @@ -826,22 +821,22 @@ class PlexClient(MediaPlayerDevice): def _client_play_media(self, media, delete=False, **params): """Instruct Plex client to play a piece of media.""" - if not (self.device and + if not (self._device and 'playback' in self._device_protocol_capabilities): _LOGGER.error("Client cannot play media: %s", self.entity_id) return import plexapi.playqueue playqueue = plexapi.playqueue.PlayQueue.create( - self.device.server, media, **params) + self._device.server, media, **params) # Delete dynamic playlists used to build playqueue (ex. play tv season) if delete: media.delete() - server_url = self.device.server.baseurl.split(':') - self.device.sendCommand('playback/playMedia', **dict({ - 'machineIdentifier': self.device.server.machineIdentifier, + server_url = self._device.server.baseurl.split(':') + self._device.sendCommand('playback/playMedia', **dict({ + 'machineIdentifier': self._device.server.machineIdentifier, 'address': server_url[1].strip('/'), 'port': server_url[-1], 'key': media.key, diff --git a/homeassistant/components/media_player/soundtouch.py b/homeassistant/components/media_player/soundtouch.py index 8f14031481a..703c9a963ee 100644 --- a/homeassistant/components/media_player/soundtouch.py +++ b/homeassistant/components/media_player/soundtouch.py @@ -166,11 +166,6 @@ class SoundTouchDevice(MediaPlayerDevice): """Return specific soundtouch configuration.""" return self._config - @property - def device(self): - """Return Soundtouch device.""" - return self._device - def update(self): """Retrieve the latest data.""" self._status = self._device.status() @@ -323,8 +318,8 @@ class SoundTouchDevice(MediaPlayerDevice): _LOGGER.warning("Unable to create zone without slaves") else: _LOGGER.info("Creating zone with master %s", - self.device.config.name) - self.device.create_zone([slave.device for slave in slaves]) + self._device.config.name) + self._device.create_zone([slave.device for slave in slaves]) def remove_zone_slave(self, slaves): """ @@ -341,8 +336,8 @@ class SoundTouchDevice(MediaPlayerDevice): _LOGGER.warning("Unable to find slaves to remove") else: _LOGGER.info("Removing slaves from zone with master %s", - self.device.config.name) - self.device.remove_zone_slave([slave.device for slave in slaves]) + self._device.config.name) + self._device.remove_zone_slave([slave.device for slave in slaves]) def add_zone_slave(self, slaves): """ @@ -357,5 +352,5 @@ class SoundTouchDevice(MediaPlayerDevice): _LOGGER.warning("Unable to find slaves to add") else: _LOGGER.info("Adding slaves to zone with master %s", - self.device.config.name) - self.device.add_zone_slave([slave.device for slave in slaves]) + self._device.config.name) + self._device.add_zone_slave([slave.device for slave in slaves]) diff --git a/homeassistant/components/nest/__init__.py b/homeassistant/components/nest/__init__.py index 57111350396..04163f1ca13 100644 --- a/homeassistant/components/nest/__init__.py +++ b/homeassistant/components/nest/__init__.py @@ -282,12 +282,12 @@ class NestSensorDevice(Entity): if device is not None: # device specific - self.device = device - self._name = "{} {}".format(self.device.name_long, + self._device = device + self._name = "{} {}".format(self._device.name_long, self.variable.replace('_', ' ')) else: # structure only - self.device = structure + self._device = structure self._name = "{} {}".format(self.structure.name, self.variable.replace('_', ' ')) diff --git a/homeassistant/components/notify/knx.py b/homeassistant/components/notify/knx.py index 750e3945569..f9a6a4b25f2 100644 --- a/homeassistant/components/notify/knx.py +++ b/homeassistant/components/notify/knx.py @@ -61,13 +61,13 @@ class KNXNotificationService(BaseNotificationService): def __init__(self, devices): """Initialize the service.""" - self.devices = devices + self._devices = devices @property def targets(self): """Return a dictionary of registered targets.""" ret = {} - for device in self.devices: + for device in self._devices: ret[device.name] = device.name return ret @@ -80,11 +80,11 @@ class KNXNotificationService(BaseNotificationService): async def _async_send_to_all_devices(self, message): """Send a notification to knx bus to all connected devices.""" - for device in self.devices: + for device in self._devices: await device.set(message) async def _async_send_to_device(self, message, names): """Send a notification to knx bus to device with given names.""" - for device in self.devices: + for device in self._devices: if device.name in names: await device.set(message) diff --git a/homeassistant/components/qwikswitch.py b/homeassistant/components/qwikswitch.py index 63e30a9491e..8af0e8db28d 100644 --- a/homeassistant/components/qwikswitch.py +++ b/homeassistant/components/qwikswitch.py @@ -98,13 +98,13 @@ class QSToggleEntity(QSEntity): def __init__(self, qsid, qsusb): """Initialize the ToggleEntity.""" - self.device = qsusb.devices[qsid] - super().__init__(qsid, self.device.name) + self._device = qsusb.devices[qsid] + super().__init__(qsid, self._device.name) @property def is_on(self): """Check if device is on (non-zero).""" - return self.device.value > 0 + return self._device.value > 0 async def async_turn_on(self, **kwargs): """Turn the device on.""" diff --git a/homeassistant/components/remote/xiaomi_miio.py b/homeassistant/components/remote/xiaomi_miio.py index 0375226adec..caab75bc841 100644 --- a/homeassistant/components/remote/xiaomi_miio.py +++ b/homeassistant/components/remote/xiaomi_miio.py @@ -187,11 +187,6 @@ class XiaomiMiioRemote(RemoteDevice): """Return the name of the remote.""" return self._name - @property - def device(self): - """Return the remote object.""" - return self._device - @property def hidden(self): """Return if we should hide entity.""" @@ -212,7 +207,7 @@ class XiaomiMiioRemote(RemoteDevice): """Return False if device is unreachable, else True.""" from miio import DeviceException try: - self.device.info() + self._device.info() return True except DeviceException: return False @@ -247,7 +242,7 @@ class XiaomiMiioRemote(RemoteDevice): _LOGGER.debug("Sending payload: '%s'", payload) try: - self.device.play(payload) + self._device.play(payload) except DeviceException as ex: _LOGGER.error( "Transmit of IR command failed, %s, exception: %s", diff --git a/homeassistant/components/sensor/juicenet.py b/homeassistant/components/sensor/juicenet.py index 0d305ca23c7..033e2d7acad 100644 --- a/homeassistant/components/sensor/juicenet.py +++ b/homeassistant/components/sensor/juicenet.py @@ -49,14 +49,14 @@ class JuicenetSensorDevice(JuicenetDevice, Entity): @property def name(self): """Return the name of the device.""" - return '{} {}'.format(self.device.name(), self._name) + return '{} {}'.format(self._device.name(), self._name) @property def icon(self): """Return the icon of the sensor.""" icon = None if self.type == 'status': - status = self.device.getStatus() + status = self._device.getStatus() if status == 'standby': icon = 'mdi:power-plug-off' elif status == 'plugged': @@ -87,19 +87,19 @@ class JuicenetSensorDevice(JuicenetDevice, Entity): """Return the state.""" state = None if self.type == 'status': - state = self.device.getStatus() + state = self._device.getStatus() elif self.type == 'temperature': - state = self.device.getTemperature() + state = self._device.getTemperature() elif self.type == 'voltage': - state = self.device.getVoltage() + state = self._device.getVoltage() elif self.type == 'amps': - state = self.device.getAmps() + state = self._device.getAmps() elif self.type == 'watts': - state = self.device.getWatts() + state = self._device.getWatts() elif self.type == 'charge_time': - state = self.device.getChargeTime() + state = self._device.getChargeTime() elif self.type == 'energy_added': - state = self.device.getEnergyAdded() + state = self._device.getEnergyAdded() else: state = 'Unknown' return state @@ -109,7 +109,7 @@ class JuicenetSensorDevice(JuicenetDevice, Entity): """Return the state attributes.""" attributes = {} if self.type == 'status': - man_dev_id = self.device.id() + man_dev_id = self._device.id() if man_dev_id: attributes["manufacturer_device_id"] = man_dev_id return attributes diff --git a/homeassistant/components/sensor/knx.py b/homeassistant/components/sensor/knx.py index 925b16cb4c7..b4d1f6653c0 100644 --- a/homeassistant/components/sensor/knx.py +++ b/homeassistant/components/sensor/knx.py @@ -64,7 +64,7 @@ class KNXSensor(Entity): def __init__(self, hass, device): """Initialize of a KNX sensor.""" - self.device = device + self._device = device self.hass = hass self.async_register_callbacks() @@ -74,12 +74,12 @@ class KNXSensor(Entity): async def after_update_callback(device): """Call after device was updated.""" await self.async_update_ha_state() - self.device.register_device_updated_cb(after_update_callback) + self._device.register_device_updated_cb(after_update_callback) @property def name(self): """Return the name of the KNX device.""" - return self.device.name + return self._device.name @property def available(self): @@ -94,12 +94,12 @@ class KNXSensor(Entity): @property def state(self): """Return the state of the sensor.""" - return self.device.resolve_state() + return self._device.resolve_state() @property def unit_of_measurement(self): """Return the unit this state is expressed in.""" - return self.device.unit_of_measurement() + return self._device.unit_of_measurement() @property def device_state_attributes(self): diff --git a/homeassistant/components/sensor/nest.py b/homeassistant/components/sensor/nest.py index d2e1501ad7e..bb1f3e67d4d 100644 --- a/homeassistant/components/sensor/nest.py +++ b/homeassistant/components/sensor/nest.py @@ -140,15 +140,15 @@ class NestBasicSensor(NestSensorDevice): self._unit = SENSOR_UNITS.get(self.variable) if self.variable in VARIABLE_NAME_MAPPING: - self._state = getattr(self.device, + self._state = getattr(self._device, VARIABLE_NAME_MAPPING[self.variable]) elif self.variable in PROTECT_SENSOR_TYPES \ and self.variable != 'color_status': # keep backward compatibility - state = getattr(self.device, self.variable) + state = getattr(self._device, self.variable) self._state = state.capitalize() if state is not None else None else: - self._state = getattr(self.device, self.variable) + self._state = getattr(self._device, self.variable) class NestTempSensor(NestSensorDevice): @@ -166,12 +166,12 @@ class NestTempSensor(NestSensorDevice): def update(self): """Retrieve latest state.""" - if self.device.temperature_scale == 'C': + if self._device.temperature_scale == 'C': self._unit = TEMP_CELSIUS else: self._unit = TEMP_FAHRENHEIT - temp = getattr(self.device, self.variable) + temp = getattr(self._device, self.variable) if temp is None: self._state = None diff --git a/homeassistant/components/sensor/tank_utility.py b/homeassistant/components/sensor/tank_utility.py index 01ace415159..1f565d44325 100644 --- a/homeassistant/components/sensor/tank_utility.py +++ b/homeassistant/components/sensor/tank_utility.py @@ -79,15 +79,10 @@ class TankUtilitySensor(Entity): self._token = token self._device = device self._state = STATE_UNKNOWN - self._name = "Tank Utility " + self.device + self._name = "Tank Utility " + self._device self._unit_of_measurement = SENSOR_UNIT_OF_MEASUREMENT self._attributes = {} - @property - def device(self): - """Return the device identifier.""" - return self._device - @property def state(self): """Return the state of the device.""" @@ -117,14 +112,14 @@ class TankUtilitySensor(Entity): from tank_utility import auth, device data = {} try: - data = device.get_device_data(self._token, self.device) + data = device.get_device_data(self._token, self._device) except requests.exceptions.HTTPError as http_error: if (http_error.response.status_code == requests.codes.unauthorized): # pylint: disable=no-member _LOGGER.info("Getting new token") self._token = auth.get_token(self._email, self._password, force=True) - data = device.get_device_data(self._token, self.device) + data = device.get_device_data(self._token, self._device) else: raise http_error data.update(data.pop("device", {})) diff --git a/homeassistant/components/sensor/tellduslive.py b/homeassistant/components/sensor/tellduslive.py index 123c11021b4..9d5a21b37c4 100644 --- a/homeassistant/components/sensor/tellduslive.py +++ b/homeassistant/components/sensor/tellduslive.py @@ -67,7 +67,7 @@ class TelldusLiveSensor(TelldusLiveEntity): @property def _value(self): """Return value of the sensor.""" - return self.device.value(*self._id[1:]) + return self._device.value(*self._id[1:]) @property def _value_as_temperature(self): diff --git a/homeassistant/components/switch/knx.py b/homeassistant/components/switch/knx.py index c13631ca5e6..4e0b29301fb 100644 --- a/homeassistant/components/switch/knx.py +++ b/homeassistant/components/switch/knx.py @@ -63,7 +63,7 @@ class KNXSwitch(SwitchDevice): def __init__(self, hass, device): """Initialize of KNX switch.""" - self.device = device + self._device = device self.hass = hass self.async_register_callbacks() @@ -73,12 +73,12 @@ class KNXSwitch(SwitchDevice): async def after_update_callback(device): """Call after device was updated.""" await self.async_update_ha_state() - self.device.register_device_updated_cb(after_update_callback) + self._device.register_device_updated_cb(after_update_callback) @property def name(self): """Return the name of the KNX device.""" - return self.device.name + return self._device.name @property def available(self): @@ -93,12 +93,12 @@ class KNXSwitch(SwitchDevice): @property def is_on(self): """Return true if device is on.""" - return self.device.state + return self._device.state async def async_turn_on(self, **kwargs): """Turn the device on.""" - await self.device.set_on() + await self._device.set_on() async def async_turn_off(self, **kwargs): """Turn the device off.""" - await self.device.set_off() + await self._device.set_off() diff --git a/homeassistant/components/switch/mochad.py b/homeassistant/components/switch/mochad.py index f80784271c2..bb3b9c0ea65 100644 --- a/homeassistant/components/switch/mochad.py +++ b/homeassistant/components/switch/mochad.py @@ -48,7 +48,7 @@ class MochadSwitch(SwitchDevice): self._address = dev[CONF_ADDRESS] self._name = dev.get(CONF_NAME, 'x10_switch_dev_%s' % self._address) self._comm_type = dev.get(mochad.CONF_COMM_TYPE, 'pl') - self.device = device.Device(ctrl, self._address, + self.switch = device.Device(ctrl, self._address, comm_type=self._comm_type) # Init with false to avoid locking HA for long on CM19A (goes from rf # to pl via TM751, but not other way around) @@ -71,7 +71,7 @@ class MochadSwitch(SwitchDevice): try: # Recycle socket on new command to recover mochad connection self._controller.reconnect() - self.device.send_cmd('on') + self.switch.send_cmd('on') # No read data on CM19A which is rf only if self._comm_type == 'pl': self._controller.read_data() @@ -88,7 +88,7 @@ class MochadSwitch(SwitchDevice): try: # Recycle socket on new command to recover mochad connection self._controller.reconnect() - self.device.send_cmd('off') + self.switch.send_cmd('off') # No read data on CM19A which is rf only if self._comm_type == 'pl': self._controller.read_data() @@ -99,7 +99,7 @@ class MochadSwitch(SwitchDevice): def _get_device_status(self): """Get the status of the switch from mochad.""" with mochad.REQ_LOCK: - status = self.device.get_status().rstrip() + status = self.switch.get_status().rstrip() return status == 'on' @property diff --git a/homeassistant/components/switch/tellduslive.py b/homeassistant/components/switch/tellduslive.py index eec63ebaa5c..ac2b569f81c 100644 --- a/homeassistant/components/switch/tellduslive.py +++ b/homeassistant/components/switch/tellduslive.py @@ -28,14 +28,14 @@ class TelldusLiveSwitch(TelldusLiveEntity, ToggleEntity): @property def is_on(self): """Return true if switch is on.""" - return self.device.is_on + return self._device.is_on def turn_on(self, **kwargs): """Turn the switch on.""" - self.device.turn_on() + self._device.turn_on() self.changed() def turn_off(self, **kwargs): """Turn the switch off.""" - self.device.turn_off() + self._device.turn_off() self.changed() diff --git a/homeassistant/components/tellduslive.py b/homeassistant/components/tellduslive.py index c2b7ba9ba0f..58be267bbbc 100644 --- a/homeassistant/components/tellduslive.py +++ b/homeassistant/components/tellduslive.py @@ -287,13 +287,14 @@ class TelldusLiveEntity(Entity): self._id = device_id self._client = hass.data[DOMAIN] self._client.entities.append(self) - self._name = self.device.name + self._device = self._client.device(device_id) + self._name = self._device.name _LOGGER.debug('Created device %s', self) def changed(self): """Return the property of the device might have changed.""" - if self.device.name: - self._name = self.device.name + if self._device.name: + self._name = self._device.name self.schedule_update_ha_state() @property @@ -301,15 +302,10 @@ class TelldusLiveEntity(Entity): """Return the id of the device.""" return self._id - @property - def device(self): - """Return the representation of the device.""" - return self._client.device(self.device_id) - @property def _state(self): """Return the state of the device.""" - return self.device.state + return self._device.state @property def should_poll(self): @@ -347,16 +343,16 @@ class TelldusLiveEntity(Entity): from tellduslive import (BATTERY_LOW, BATTERY_UNKNOWN, BATTERY_OK) - if self.device.battery == BATTERY_LOW: + if self._device.battery == BATTERY_LOW: return 1 - if self.device.battery == BATTERY_UNKNOWN: + if self._device.battery == BATTERY_UNKNOWN: return None - if self.device.battery == BATTERY_OK: + if self._device.battery == BATTERY_OK: return 100 - return self.device.battery # Percentage + return self._device.battery # Percentage @property def _last_updated(self): """Return the last update of a device.""" - return str(datetime.fromtimestamp(self.device.lastUpdated)) \ - if self.device.lastUpdated else None + return str(datetime.fromtimestamp(self._device.lastUpdated)) \ + if self._device.lastUpdated else None diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py new file mode 100644 index 00000000000..78b38afa438 --- /dev/null +++ b/homeassistant/helpers/device_registry.py @@ -0,0 +1,121 @@ +"""Provide a way to connect entities belonging to one device.""" +import logging +import uuid + +import attr + +from homeassistant.core import callback +from homeassistant.loader import bind_hass + +_LOGGER = logging.getLogger(__name__) + +DATA_REGISTRY = 'device_registry' + +STORAGE_KEY = 'core.device_registry' +STORAGE_VERSION = 1 +SAVE_DELAY = 10 + + +@attr.s(slots=True, frozen=True) +class DeviceEntry: + """Device Registry Entry.""" + + identifiers = attr.ib(type=list) + manufacturer = attr.ib(type=str) + model = attr.ib(type=str) + connection = attr.ib(type=list) + name = attr.ib(type=str, default=None) + sw_version = attr.ib(type=str, default=None) + id = attr.ib(type=str, default=attr.Factory(lambda: uuid.uuid4().hex)) + + +class DeviceRegistry: + """Class to hold a registry of devices.""" + + def __init__(self, hass): + """Initialize the device registry.""" + self.hass = hass + self.devices = None + self._store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) + + @callback + def async_get_device(self, identifiers: str, connections: tuple): + """Check if device is registered.""" + for device in self.devices: + if any(iden in device.identifiers for iden in identifiers) or \ + any(conn in device.connection for conn in connections): + return device + return None + + @callback + def async_get_or_create(self, identifiers, manufacturer, model, + connection, *, name=None, sw_version=None): + """Get device. Create if it doesn't exist.""" + device = self.async_get_device(identifiers, connection) + + if device is not None: + return device + + device = DeviceEntry( + identifiers=identifiers, + manufacturer=manufacturer, + model=model, + connection=connection, + name=name, + sw_version=sw_version + ) + + self.devices.append(device) + self.async_schedule_save() + + return device + + async def async_load(self): + """Load the device registry.""" + devices = await self._store.async_load() + + if devices is None: + self.devices = [] + return + + self.devices = [DeviceEntry(**device) for device in devices['devices']] + + @callback + def async_schedule_save(self): + """Schedule saving the device registry.""" + self._store.async_delay_save(self._data_to_save, SAVE_DELAY) + + @callback + def _data_to_save(self): + """Data of device registry to store in a file.""" + data = {} + + data['devices'] = [ + { + 'id': entry.id, + 'identifiers': entry.identifiers, + 'manufacturer': entry.manufacturer, + 'model': entry.model, + 'connection': entry.connection, + 'name': entry.name, + 'sw_version': entry.sw_version, + } for entry in self.devices + ] + + return data + + +@bind_hass +async def async_get_registry(hass) -> DeviceRegistry: + """Return device registry instance.""" + task = hass.data.get(DATA_REGISTRY) + + if task is None: + async def _load_reg(): + registry = DeviceRegistry(hass) + await registry.async_load() + return registry + + task = hass.data[DATA_REGISTRY] = hass.async_create_task(_load_reg()) + + return await task diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index f27a387b9ee..6d7392d00bf 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -130,6 +130,14 @@ class Entity: """ return None + @property + def device(self): + """Return device specific attributes. + + Implemented by platform classes. + """ + return None + @property def device_class(self) -> str: """Return the class of this device, from component DEVICE_CLASSES.""" diff --git a/homeassistant/helpers/entity_platform.py b/homeassistant/helpers/entity_platform.py index bda3db7ebd9..fa880b014ec 100644 --- a/homeassistant/helpers/entity_platform.py +++ b/homeassistant/helpers/entity_platform.py @@ -8,7 +8,6 @@ from homeassistant.util.async_ import ( run_callback_threadsafe, run_coroutine_threadsafe) from .event import async_track_time_interval, async_call_later -from .entity_registry import async_get_registry SLOW_SETUP_WARNING = 10 SLOW_SETUP_MAX_WAIT = 60 @@ -209,11 +208,14 @@ class EntityPlatform: hass = self.hass component_entities = set(hass.states.async_entity_ids(self.domain)) - registry = await async_get_registry(hass) - + device_registry = await \ + hass.helpers.device_registry.async_get_registry() + entity_registry = await \ + hass.helpers.entity_registry.async_get_registry() tasks = [ self._async_add_entity(entity, update_before_add, - component_entities, registry) + component_entities, entity_registry, + device_registry) for entity in new_entities] # No entities for processing @@ -233,7 +235,8 @@ class EntityPlatform: ) async def _async_add_entity(self, entity, update_before_add, - component_entities, registry): + component_entities, entity_registry, + device_registry): """Helper method to add an entity to the platform.""" if entity is None: raise ValueError('Entity cannot be None') @@ -269,10 +272,21 @@ class EntityPlatform: else: config_entry_id = None - entry = registry.async_get_or_create( + device = entity.device + if device is not None: + device = device_registry.async_get_or_create( + device['identifiers'], device['manufacturer'], + device['model'], device['connection'], + sw_version=device.get('sw_version')) + device_id = device.id + else: + device_id = None + + entry = entity_registry.async_get_or_create( self.domain, self.platform_name, entity.unique_id, suggested_object_id=suggested_object_id, - config_entry_id=config_entry_id) + config_entry_id=config_entry_id, + device_id=device_id) if entry.disabled: self.logger.info( @@ -288,7 +302,7 @@ class EntityPlatform: # We won't generate an entity ID if the platform has already set one # We will however make sure that platform cannot pick a registered ID elif (entity.entity_id is not None and - registry.async_is_registered(entity.entity_id)): + entity_registry.async_is_registered(entity.entity_id)): # If entity already registered, convert entity id to suggestion suggested_object_id = split_entity_id(entity.entity_id)[1] entity.entity_id = None @@ -302,7 +316,7 @@ class EntityPlatform: suggested_object_id = '{} {}'.format(self.entity_namespace, suggested_object_id) - entity.entity_id = registry.async_generate_entity_id( + entity.entity_id = entity_registry.async_generate_entity_id( self.domain, suggested_object_id) # Make sure it is valid in case an entity set the value themselves diff --git a/homeassistant/helpers/entity_registry.py b/homeassistant/helpers/entity_registry.py index 285d4cbd23a..9c478b0b848 100644 --- a/homeassistant/helpers/entity_registry.py +++ b/homeassistant/helpers/entity_registry.py @@ -39,6 +39,7 @@ class RegistryEntry: unique_id = attr.ib(type=str) platform = attr.ib(type=str) name = attr.ib(type=str, default=None) + device_id = attr.ib(type=str, default=None) config_entry_id = attr.ib(type=str, default=None) disabled_by = attr.ib( type=str, default=None, @@ -107,7 +108,8 @@ class EntityRegistry: @callback def async_get_or_create(self, domain, platform, unique_id, *, - suggested_object_id=None, config_entry_id=None): + suggested_object_id=None, config_entry_id=None, + device_id=None): """Get entity. Create if it doesn't exist.""" entity_id = self.async_get_entity_id(domain, platform, unique_id) if entity_id: @@ -116,7 +118,8 @@ class EntityRegistry: return entry self._async_update_entity( - entity_id, config_entry_id=config_entry_id) + entity_id, config_entry_id=config_entry_id, + device_id=device_id) return self.entities[entity_id] entity_id = self.async_generate_entity_id( @@ -125,6 +128,7 @@ class EntityRegistry: entity = RegistryEntry( entity_id=entity_id, config_entry_id=config_entry_id, + device_id=device_id, unique_id=unique_id, platform=platform, ) @@ -146,7 +150,8 @@ class EntityRegistry: @callback def _async_update_entity(self, entity_id, *, name=_UNDEF, - config_entry_id=_UNDEF, new_entity_id=_UNDEF): + config_entry_id=_UNDEF, new_entity_id=_UNDEF, + device_id=_UNDEF): """Private facing update properties method.""" old = self.entities[entity_id] @@ -159,6 +164,9 @@ class EntityRegistry: config_entry_id != old.config_entry_id): changes['config_entry_id'] = config_entry_id + if (device_id is not _UNDEF and device_id != old.device_id): + changes['device_id'] = device_id + if new_entity_id is not _UNDEF and new_entity_id != old.entity_id: if self.async_is_registered(new_entity_id): raise ValueError('Entity is already registered') @@ -210,6 +218,7 @@ class EntityRegistry: entities[entity['entity_id']] = RegistryEntry( entity_id=entity['entity_id'], config_entry_id=entity.get('config_entry_id'), + device_id=entity.get('device_id'), unique_id=entity['unique_id'], platform=entity['platform'], name=entity.get('name'), @@ -232,6 +241,7 @@ class EntityRegistry: { 'entity_id': entry.entity_id, 'config_entry_id': entry.config_entry_id, + 'device_id': entry.device_id, 'unique_id': entry.unique_id, 'platform': entry.platform, 'name': entry.name, diff --git a/tests/components/light/test_mochad.py b/tests/components/light/test_mochad.py index 68cdffcd999..fa122777ca4 100644 --- a/tests/components/light/test_mochad.py +++ b/tests/components/light/test_mochad.py @@ -76,18 +76,18 @@ class TestMochadLight(unittest.TestCase): def test_turn_on_with_no_brightness(self): """Test turn_on.""" self.light.turn_on() - self.light.device.send_cmd.assert_called_once_with('on') + self.light.light.send_cmd.assert_called_once_with('on') def test_turn_on_with_brightness(self): """Test turn_on.""" self.light.turn_on(brightness=45) - self.light.device.send_cmd.assert_has_calls( + self.light.light.send_cmd.assert_has_calls( [mock.call('on'), mock.call('dim 25')]) def test_turn_off(self): """Test turn_off.""" self.light.turn_off() - self.light.device.send_cmd.assert_called_once_with('off') + self.light.light.send_cmd.assert_called_once_with('off') class TestMochadLight256Levels(unittest.TestCase): @@ -109,17 +109,17 @@ class TestMochadLight256Levels(unittest.TestCase): def test_turn_on_with_no_brightness(self): """Test turn_on.""" self.light.turn_on() - self.light.device.send_cmd.assert_called_once_with('xdim 255') + self.light.light.send_cmd.assert_called_once_with('xdim 255') def test_turn_on_with_brightness(self): """Test turn_on.""" self.light.turn_on(brightness=45) - self.light.device.send_cmd.assert_called_once_with('xdim 45') + self.light.light.send_cmd.assert_called_once_with('xdim 45') def test_turn_off(self): """Test turn_off.""" self.light.turn_off() - self.light.device.send_cmd.assert_called_once_with('off') + self.light.light.send_cmd.assert_called_once_with('off') class TestMochadLight64Levels(unittest.TestCase): @@ -141,14 +141,14 @@ class TestMochadLight64Levels(unittest.TestCase): def test_turn_on_with_no_brightness(self): """Test turn_on.""" self.light.turn_on() - self.light.device.send_cmd.assert_called_once_with('xdim 63') + self.light.light.send_cmd.assert_called_once_with('xdim 63') def test_turn_on_with_brightness(self): """Test turn_on.""" self.light.turn_on(brightness=45) - self.light.device.send_cmd.assert_called_once_with('xdim 11') + self.light.light.send_cmd.assert_called_once_with('xdim 11') def test_turn_off(self): """Test turn_off.""" self.light.turn_off() - self.light.device.send_cmd.assert_called_once_with('off') + self.light.light.send_cmd.assert_called_once_with('off') diff --git a/tests/components/switch/test_mochad.py b/tests/components/switch/test_mochad.py index f241a4b9f61..bfbd67e6b0c 100644 --- a/tests/components/switch/test_mochad.py +++ b/tests/components/switch/test_mochad.py @@ -76,9 +76,9 @@ class TestMochadSwitch(unittest.TestCase): def test_turn_on(self): """Test turn_on.""" self.switch.turn_on() - self.switch.device.send_cmd.assert_called_once_with('on') + self.switch.switch.send_cmd.assert_called_once_with('on') def test_turn_off(self): """Test turn_off.""" self.switch.turn_off() - self.switch.device.send_cmd.assert_called_once_with('off') + self.switch.switch.send_cmd.assert_called_once_with('off') diff --git a/tests/helpers/test_device_registry.py b/tests/helpers/test_device_registry.py new file mode 100644 index 00000000000..41e7d39e977 --- /dev/null +++ b/tests/helpers/test_device_registry.py @@ -0,0 +1,78 @@ +"""Tests for the Device Registry.""" +import pytest + +from homeassistant.helpers import device_registry + + +def mock_registry(hass, mock_entries=None): + """Mock the Device Registry.""" + registry = device_registry.DeviceRegistry(hass) + registry.devices = mock_entries or [] + + async def _get_reg(): + return registry + + hass.data[device_registry.DATA_REGISTRY] = \ + hass.loop.create_task(_get_reg()) + return registry + + +@pytest.fixture +def registry(hass): + """Return an empty, loaded, registry.""" + return mock_registry(hass) + + +async def test_get_or_create_returns_same_entry(registry): + """Make sure we do not duplicate entries.""" + entry = registry.async_get_or_create( + [['bridgeid', '0123']], 'manufacturer', 'model', + [['ethernet', '12:34:56:78:90:AB:CD:EF']]) + entry2 = registry.async_get_or_create( + [['bridgeid', '0123']], 'manufacturer', 'model', + [['ethernet', '11:22:33:44:55:66:77:88']]) + entry3 = registry.async_get_or_create( + [['bridgeid', '1234']], 'manufacturer', 'model', + [['ethernet', '12:34:56:78:90:AB:CD:EF']]) + + assert len(registry.devices) == 1 + assert entry is entry2 + assert entry is entry3 + assert entry.identifiers == [['bridgeid', '0123']] + + +async def test_loading_from_storage(hass, hass_storage): + """Test loading stored devices on start.""" + hass_storage[device_registry.STORAGE_KEY] = { + 'version': device_registry.STORAGE_VERSION, + 'data': { + 'devices': [ + { + 'connection': [ + [ + 'Zigbee', + '01.23.45.67.89' + ] + ], + 'id': 'abcdefghijklm', + 'identifiers': [ + [ + 'serial', + '12:34:56:78:90:AB:CD:EF' + ] + ], + 'manufacturer': 'manufacturer', + 'model': 'model', + 'name': 'name', + 'sw_version': 'version' + } + ] + } + } + + registry = await device_registry.async_get_registry(hass) + + entry = registry.async_get_or_create( + [['serial', '12:34:56:78:90:AB:CD:EF']], 'manufacturer', + 'model', [['Zigbee', '01.23.45.67.89']]) + assert entry.id == 'abcdefghijklm'