Update rfxtrx component so it can be run as a custom_component (#29638)
* Updating rfxtrx component so it can be run as a custom_component * Fix pylint errors * Fix pylint errors * Fix pylint error on dict. * isort
This commit is contained in:
parent
856dd63680
commit
a08e3d7352
5 changed files with 64 additions and 46 deletions
|
@ -4,7 +4,6 @@ import logging
|
||||||
import RFXtrx as rfxtrxmod
|
import RFXtrx as rfxtrxmod
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import rfxtrx
|
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
DEVICE_CLASSES_SCHEMA,
|
DEVICE_CLASSES_SCHEMA,
|
||||||
PLATFORM_SCHEMA,
|
PLATFORM_SCHEMA,
|
||||||
|
@ -26,6 +25,14 @@ from . import (
|
||||||
CONF_DEVICES,
|
CONF_DEVICES,
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_OFF_DELAY,
|
CONF_OFF_DELAY,
|
||||||
|
RECEIVED_EVT_SUBSCRIBERS,
|
||||||
|
RFX_DEVICES,
|
||||||
|
apply_received_command,
|
||||||
|
find_possible_pt2262_device,
|
||||||
|
get_pt2262_cmd,
|
||||||
|
get_pt2262_device,
|
||||||
|
get_pt2262_deviceid,
|
||||||
|
get_rfx_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -58,16 +65,16 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
sensors = []
|
sensors = []
|
||||||
|
|
||||||
for packet_id, entity in config[CONF_DEVICES].items():
|
for packet_id, entity in config[CONF_DEVICES].items():
|
||||||
event = rfxtrx.get_rfx_object(packet_id)
|
event = get_rfx_object(packet_id)
|
||||||
device_id = slugify(event.device.id_string.lower())
|
device_id = slugify(event.device.id_string.lower())
|
||||||
|
|
||||||
if device_id in rfxtrx.RFX_DEVICES:
|
if device_id in RFX_DEVICES:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if entity.get(CONF_DATA_BITS) is not None:
|
if entity.get(CONF_DATA_BITS) is not None:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Masked device id: %s",
|
"Masked device id: %s",
|
||||||
rfxtrx.get_pt2262_deviceid(device_id, entity.get(CONF_DATA_BITS)),
|
get_pt2262_deviceid(device_id, entity.get(CONF_DATA_BITS)),
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
|
@ -88,7 +95,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
)
|
)
|
||||||
device.hass = hass
|
device.hass = hass
|
||||||
sensors.append(device)
|
sensors.append(device)
|
||||||
rfxtrx.RFX_DEVICES[device_id] = device
|
RFX_DEVICES[device_id] = device
|
||||||
|
|
||||||
add_entities(sensors)
|
add_entities(sensors)
|
||||||
|
|
||||||
|
@ -99,10 +106,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
|
|
||||||
device_id = slugify(event.device.id_string.lower())
|
device_id = slugify(event.device.id_string.lower())
|
||||||
|
|
||||||
if device_id in rfxtrx.RFX_DEVICES:
|
sensor = RFX_DEVICES.get(device_id, get_pt2262_device(device_id))
|
||||||
sensor = rfxtrx.RFX_DEVICES[device_id]
|
|
||||||
else:
|
|
||||||
sensor = rfxtrx.get_pt2262_device(device_id)
|
|
||||||
|
|
||||||
if sensor is None:
|
if sensor is None:
|
||||||
# Add the entity if not exists and automatic_add is True
|
# Add the entity if not exists and automatic_add is True
|
||||||
|
@ -110,7 +114,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
return
|
return
|
||||||
|
|
||||||
if event.device.packettype == 0x13:
|
if event.device.packettype == 0x13:
|
||||||
poss_dev = rfxtrx.find_possible_pt2262_device(device_id)
|
poss_dev = find_possible_pt2262_device(device_id)
|
||||||
if poss_dev is not None:
|
if poss_dev is not None:
|
||||||
poss_id = slugify(poss_dev.event.device.id_string.lower())
|
poss_id = slugify(poss_dev.event.device.id_string.lower())
|
||||||
_LOGGER.debug("Found possible matching device ID: %s", poss_id)
|
_LOGGER.debug("Found possible matching device ID: %s", poss_id)
|
||||||
|
@ -118,7 +122,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
pkt_id = "".join(f"{x:02x}" for x in event.data)
|
pkt_id = "".join(f"{x:02x}" for x in event.data)
|
||||||
sensor = RfxtrxBinarySensor(event, pkt_id)
|
sensor = RfxtrxBinarySensor(event, pkt_id)
|
||||||
sensor.hass = hass
|
sensor.hass = hass
|
||||||
rfxtrx.RFX_DEVICES[device_id] = sensor
|
RFX_DEVICES[device_id] = sensor
|
||||||
add_entities([sensor])
|
add_entities([sensor])
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Added binary sensor %s (Device ID: %s Class: %s Sub: %s)",
|
"Added binary sensor %s (Device ID: %s Class: %s Sub: %s)",
|
||||||
|
@ -140,12 +144,12 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
|
|
||||||
if sensor.is_lighting4:
|
if sensor.is_lighting4:
|
||||||
if sensor.data_bits is not None:
|
if sensor.data_bits is not None:
|
||||||
cmd = rfxtrx.get_pt2262_cmd(device_id, sensor.data_bits)
|
cmd = get_pt2262_cmd(device_id, sensor.data_bits)
|
||||||
sensor.apply_cmd(int(cmd, 16))
|
sensor.apply_cmd(int(cmd, 16))
|
||||||
else:
|
else:
|
||||||
sensor.update_state(True)
|
sensor.update_state(True)
|
||||||
else:
|
else:
|
||||||
rfxtrx.apply_received_command(event)
|
apply_received_command(event)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
sensor.is_on
|
sensor.is_on
|
||||||
|
@ -163,8 +167,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
if binary_sensor_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
|
if binary_sensor_update not in RECEIVED_EVT_SUBSCRIBERS:
|
||||||
rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(binary_sensor_update)
|
RECEIVED_EVT_SUBSCRIBERS.append(binary_sensor_update)
|
||||||
|
|
||||||
|
|
||||||
class RfxtrxBinarySensor(BinarySensorDevice):
|
class RfxtrxBinarySensor(BinarySensorDevice):
|
||||||
|
@ -195,7 +199,7 @@ class RfxtrxBinarySensor(BinarySensorDevice):
|
||||||
self._cmd_off = cmd_off
|
self._cmd_off = cmd_off
|
||||||
|
|
||||||
if data_bits is not None:
|
if data_bits is not None:
|
||||||
self._masked_id = rfxtrx.get_pt2262_deviceid(
|
self._masked_id = get_pt2262_deviceid(
|
||||||
event.device.id_string.lower(), data_bits
|
event.device.id_string.lower(), data_bits
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
import RFXtrx as rfxtrxmod
|
import RFXtrx as rfxtrxmod
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import rfxtrx
|
|
||||||
from homeassistant.components.cover import PLATFORM_SCHEMA, CoverDevice
|
from homeassistant.components.cover import PLATFORM_SCHEMA, CoverDevice
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
@ -13,6 +12,11 @@ from . import (
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_SIGNAL_REPETITIONS,
|
CONF_SIGNAL_REPETITIONS,
|
||||||
DEFAULT_SIGNAL_REPETITIONS,
|
DEFAULT_SIGNAL_REPETITIONS,
|
||||||
|
RECEIVED_EVT_SUBSCRIBERS,
|
||||||
|
RfxtrxDevice,
|
||||||
|
apply_received_command,
|
||||||
|
get_devices_from_config,
|
||||||
|
get_new_device,
|
||||||
)
|
)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
|
@ -35,7 +39,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the RFXtrx cover."""
|
"""Set up the RFXtrx cover."""
|
||||||
covers = rfxtrx.get_devices_from_config(config, RfxtrxCover)
|
covers = get_devices_from_config(config, RfxtrxCover)
|
||||||
add_entities(covers)
|
add_entities(covers)
|
||||||
|
|
||||||
def cover_update(event):
|
def cover_update(event):
|
||||||
|
@ -47,18 +51,18 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
new_device = rfxtrx.get_new_device(event, config, RfxtrxCover)
|
new_device = get_new_device(event, config, RfxtrxCover)
|
||||||
if new_device:
|
if new_device:
|
||||||
add_entities([new_device])
|
add_entities([new_device])
|
||||||
|
|
||||||
rfxtrx.apply_received_command(event)
|
apply_received_command(event)
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
if cover_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
|
if cover_update not in RECEIVED_EVT_SUBSCRIBERS:
|
||||||
rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(cover_update)
|
RECEIVED_EVT_SUBSCRIBERS.append(cover_update)
|
||||||
|
|
||||||
|
|
||||||
class RfxtrxCover(rfxtrx.RfxtrxDevice, CoverDevice):
|
class RfxtrxCover(RfxtrxDevice, CoverDevice):
|
||||||
"""Representation of a RFXtrx cover."""
|
"""Representation of a RFXtrx cover."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -4,7 +4,6 @@ import logging
|
||||||
import RFXtrx as rfxtrxmod
|
import RFXtrx as rfxtrxmod
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import rfxtrx
|
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
PLATFORM_SCHEMA,
|
PLATFORM_SCHEMA,
|
||||||
|
@ -20,6 +19,11 @@ from . import (
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_SIGNAL_REPETITIONS,
|
CONF_SIGNAL_REPETITIONS,
|
||||||
DEFAULT_SIGNAL_REPETITIONS,
|
DEFAULT_SIGNAL_REPETITIONS,
|
||||||
|
RECEIVED_EVT_SUBSCRIBERS,
|
||||||
|
RfxtrxDevice,
|
||||||
|
apply_received_command,
|
||||||
|
get_devices_from_config,
|
||||||
|
get_new_device,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -46,7 +50,7 @@ SUPPORT_RFXTRX = SUPPORT_BRIGHTNESS
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the RFXtrx platform."""
|
"""Set up the RFXtrx platform."""
|
||||||
lights = rfxtrx.get_devices_from_config(config, RfxtrxLight)
|
lights = get_devices_from_config(config, RfxtrxLight)
|
||||||
add_entities(lights)
|
add_entities(lights)
|
||||||
|
|
||||||
def light_update(event):
|
def light_update(event):
|
||||||
|
@ -57,18 +61,18 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
new_device = rfxtrx.get_new_device(event, config, RfxtrxLight)
|
new_device = get_new_device(event, config, RfxtrxLight)
|
||||||
if new_device:
|
if new_device:
|
||||||
add_entities([new_device])
|
add_entities([new_device])
|
||||||
|
|
||||||
rfxtrx.apply_received_command(event)
|
apply_received_command(event)
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
if light_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
|
if light_update not in RECEIVED_EVT_SUBSCRIBERS:
|
||||||
rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(light_update)
|
RECEIVED_EVT_SUBSCRIBERS.append(light_update)
|
||||||
|
|
||||||
|
|
||||||
class RfxtrxLight(rfxtrx.RfxtrxDevice, Light):
|
class RfxtrxLight(RfxtrxDevice, Light):
|
||||||
"""Representation of a RFXtrx light."""
|
"""Representation of a RFXtrx light."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -4,7 +4,6 @@ import logging
|
||||||
from RFXtrx import SensorEvent
|
from RFXtrx import SensorEvent
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import rfxtrx
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME, CONF_NAME
|
from homeassistant.const import ATTR_ENTITY_ID, ATTR_NAME, CONF_NAME
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
@ -19,6 +18,9 @@ from . import (
|
||||||
CONF_DEVICES,
|
CONF_DEVICES,
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
DATA_TYPES,
|
DATA_TYPES,
|
||||||
|
RECEIVED_EVT_SUBSCRIBERS,
|
||||||
|
RFX_DEVICES,
|
||||||
|
get_rfx_object,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -46,9 +48,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up the RFXtrx platform."""
|
"""Set up the RFXtrx platform."""
|
||||||
sensors = []
|
sensors = []
|
||||||
for packet_id, entity_info in config[CONF_DEVICES].items():
|
for packet_id, entity_info in config[CONF_DEVICES].items():
|
||||||
event = rfxtrx.get_rfx_object(packet_id)
|
event = get_rfx_object(packet_id)
|
||||||
device_id = "sensor_{}".format(slugify(event.device.id_string.lower()))
|
device_id = "sensor_{}".format(slugify(event.device.id_string.lower()))
|
||||||
if device_id in rfxtrx.RFX_DEVICES:
|
if device_id in RFX_DEVICES:
|
||||||
continue
|
continue
|
||||||
_LOGGER.info("Add %s rfxtrx.sensor", entity_info[ATTR_NAME])
|
_LOGGER.info("Add %s rfxtrx.sensor", entity_info[ATTR_NAME])
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
)
|
)
|
||||||
sensors.append(new_sensor)
|
sensors.append(new_sensor)
|
||||||
sub_sensors[_data_type] = new_sensor
|
sub_sensors[_data_type] = new_sensor
|
||||||
rfxtrx.RFX_DEVICES[device_id] = sub_sensors
|
RFX_DEVICES[device_id] = sub_sensors
|
||||||
add_entities(sensors)
|
add_entities(sensors)
|
||||||
|
|
||||||
def sensor_update(event):
|
def sensor_update(event):
|
||||||
|
@ -76,8 +78,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
|
|
||||||
device_id = "sensor_" + slugify(event.device.id_string.lower())
|
device_id = "sensor_" + slugify(event.device.id_string.lower())
|
||||||
|
|
||||||
if device_id in rfxtrx.RFX_DEVICES:
|
if device_id in RFX_DEVICES:
|
||||||
sensors = rfxtrx.RFX_DEVICES[device_id]
|
sensors = RFX_DEVICES[device_id]
|
||||||
for data_type in sensors:
|
for data_type in sensors:
|
||||||
# Some multi-sensor devices send individual messages for each
|
# Some multi-sensor devices send individual messages for each
|
||||||
# of their sensors. Update only if event contains the
|
# of their sensors. Update only if event contains the
|
||||||
|
@ -108,11 +110,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
new_sensor = RfxtrxSensor(event, pkt_id, data_type)
|
new_sensor = RfxtrxSensor(event, pkt_id, data_type)
|
||||||
sub_sensors = {}
|
sub_sensors = {}
|
||||||
sub_sensors[new_sensor.data_type] = new_sensor
|
sub_sensors[new_sensor.data_type] = new_sensor
|
||||||
rfxtrx.RFX_DEVICES[device_id] = sub_sensors
|
RFX_DEVICES[device_id] = sub_sensors
|
||||||
add_entities([new_sensor])
|
add_entities([new_sensor])
|
||||||
|
|
||||||
if sensor_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
|
if sensor_update not in RECEIVED_EVT_SUBSCRIBERS:
|
||||||
rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(sensor_update)
|
RECEIVED_EVT_SUBSCRIBERS.append(sensor_update)
|
||||||
|
|
||||||
|
|
||||||
class RfxtrxSensor(Entity):
|
class RfxtrxSensor(Entity):
|
||||||
|
|
|
@ -4,7 +4,6 @@ import logging
|
||||||
import RFXtrx as rfxtrxmod
|
import RFXtrx as rfxtrxmod
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import rfxtrx
|
|
||||||
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice
|
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
|
@ -15,6 +14,11 @@ from . import (
|
||||||
CONF_FIRE_EVENT,
|
CONF_FIRE_EVENT,
|
||||||
CONF_SIGNAL_REPETITIONS,
|
CONF_SIGNAL_REPETITIONS,
|
||||||
DEFAULT_SIGNAL_REPETITIONS,
|
DEFAULT_SIGNAL_REPETITIONS,
|
||||||
|
RECEIVED_EVT_SUBSCRIBERS,
|
||||||
|
RfxtrxDevice,
|
||||||
|
apply_received_command,
|
||||||
|
get_devices_from_config,
|
||||||
|
get_new_device,
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -40,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||||
def setup_platform(hass, config, add_entities_callback, discovery_info=None):
|
def setup_platform(hass, config, add_entities_callback, discovery_info=None):
|
||||||
"""Set up the RFXtrx platform."""
|
"""Set up the RFXtrx platform."""
|
||||||
# Add switch from config file
|
# Add switch from config file
|
||||||
switches = rfxtrx.get_devices_from_config(config, RfxtrxSwitch)
|
switches = get_devices_from_config(config, RfxtrxSwitch)
|
||||||
add_entities_callback(switches)
|
add_entities_callback(switches)
|
||||||
|
|
||||||
def switch_update(event):
|
def switch_update(event):
|
||||||
|
@ -52,18 +56,18 @@ def setup_platform(hass, config, add_entities_callback, discovery_info=None):
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
new_device = rfxtrx.get_new_device(event, config, RfxtrxSwitch)
|
new_device = get_new_device(event, config, RfxtrxSwitch)
|
||||||
if new_device:
|
if new_device:
|
||||||
add_entities_callback([new_device])
|
add_entities_callback([new_device])
|
||||||
|
|
||||||
rfxtrx.apply_received_command(event)
|
apply_received_command(event)
|
||||||
|
|
||||||
# Subscribe to main RFXtrx events
|
# Subscribe to main RFXtrx events
|
||||||
if switch_update not in rfxtrx.RECEIVED_EVT_SUBSCRIBERS:
|
if switch_update not in RECEIVED_EVT_SUBSCRIBERS:
|
||||||
rfxtrx.RECEIVED_EVT_SUBSCRIBERS.append(switch_update)
|
RECEIVED_EVT_SUBSCRIBERS.append(switch_update)
|
||||||
|
|
||||||
|
|
||||||
class RfxtrxSwitch(rfxtrx.RfxtrxDevice, SwitchDevice):
|
class RfxtrxSwitch(RfxtrxDevice, SwitchDevice):
|
||||||
"""Representation of a RFXtrx switch."""
|
"""Representation of a RFXtrx switch."""
|
||||||
|
|
||||||
def turn_on(self, **kwargs):
|
def turn_on(self, **kwargs):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue