mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
Remove XBee integration (#75502)
This commit is contained in:
parent
877a4030aa
commit
87cfe21567
@ -1523,7 +1523,6 @@ omit =
|
|||||||
homeassistant/components/zha/light.py
|
homeassistant/components/zha/light.py
|
||||||
homeassistant/components/zha/sensor.py
|
homeassistant/components/zha/sensor.py
|
||||||
homeassistant/components/zhong_hong/climate.py
|
homeassistant/components/zhong_hong/climate.py
|
||||||
homeassistant/components/xbee/*
|
|
||||||
homeassistant/components/ziggo_mediabox_xl/media_player.py
|
homeassistant/components/ziggo_mediabox_xl/media_player.py
|
||||||
homeassistant/components/zoneminder/*
|
homeassistant/components/zoneminder/*
|
||||||
homeassistant/components/supla/*
|
homeassistant/components/supla/*
|
||||||
|
@ -1,441 +0,0 @@
|
|||||||
"""Support for XBee Zigbee devices."""
|
|
||||||
# pylint: disable=import-error
|
|
||||||
from binascii import hexlify, unhexlify
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from serial import Serial, SerialException
|
|
||||||
import voluptuous as vol
|
|
||||||
from xbee_helper import ZigBee
|
|
||||||
import xbee_helper.const as xb_const
|
|
||||||
from xbee_helper.device import convert_adc
|
|
||||||
from xbee_helper.exceptions import ZigBeeException, ZigBeeTxFailure
|
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorEntity
|
|
||||||
from homeassistant.const import (
|
|
||||||
CONF_ADDRESS,
|
|
||||||
CONF_DEVICE,
|
|
||||||
CONF_NAME,
|
|
||||||
CONF_PIN,
|
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
|
||||||
PERCENTAGE,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
from homeassistant.helpers import config_validation as cv
|
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect, dispatcher_send
|
|
||||||
from homeassistant.helpers.entity import Entity
|
|
||||||
from homeassistant.helpers.typing import ConfigType
|
|
||||||
|
|
||||||
from .const import DOMAIN
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
SIGNAL_XBEE_FRAME_RECEIVED = "xbee_frame_received"
|
|
||||||
|
|
||||||
CONF_BAUD = "baud"
|
|
||||||
|
|
||||||
DEFAULT_DEVICE = "/dev/ttyUSB0"
|
|
||||||
DEFAULT_BAUD = 9600
|
|
||||||
DEFAULT_ADC_MAX_VOLTS = 1.2
|
|
||||||
|
|
||||||
ATTR_FRAME = "frame"
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
DOMAIN: vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Optional(CONF_BAUD, default=DEFAULT_BAUD): cv.string,
|
|
||||||
vol.Optional(CONF_DEVICE, default=DEFAULT_DEVICE): cv.string,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
extra=vol.ALLOW_EXTRA,
|
|
||||||
)
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.Schema(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_NAME): cv.string,
|
|
||||||
vol.Optional(CONF_PIN): cv.positive_int,
|
|
||||||
vol.Optional(CONF_ADDRESS): cv.string,
|
|
||||||
},
|
|
||||||
extra=vol.ALLOW_EXTRA,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|
||||||
"""Set up the connection to the XBee Zigbee device."""
|
|
||||||
usb_device = config[DOMAIN].get(CONF_DEVICE, DEFAULT_DEVICE)
|
|
||||||
baud = int(config[DOMAIN].get(CONF_BAUD, DEFAULT_BAUD))
|
|
||||||
try:
|
|
||||||
ser = Serial(usb_device, baud)
|
|
||||||
except SerialException as exc:
|
|
||||||
_LOGGER.exception("Unable to open serial port for XBee: %s", exc)
|
|
||||||
return False
|
|
||||||
zigbee_device = ZigBee(ser)
|
|
||||||
|
|
||||||
def close_serial_port(*args):
|
|
||||||
"""Close the serial port we're using to communicate with the XBee."""
|
|
||||||
zigbee_device.zb.serial.close()
|
|
||||||
|
|
||||||
def _frame_received(frame):
|
|
||||||
"""Run when a XBee Zigbee frame is received.
|
|
||||||
|
|
||||||
Pickles the frame, then encodes it into base64 since it contains
|
|
||||||
non JSON serializable binary.
|
|
||||||
"""
|
|
||||||
dispatcher_send(hass, SIGNAL_XBEE_FRAME_RECEIVED, frame)
|
|
||||||
|
|
||||||
hass.data[DOMAIN] = zigbee_device
|
|
||||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, close_serial_port)
|
|
||||||
zigbee_device.add_frame_rx_handler(_frame_received)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def frame_is_relevant(entity, frame):
|
|
||||||
"""Test whether the frame is relevant to the entity."""
|
|
||||||
if frame.get("source_addr_long") != entity.config.address:
|
|
||||||
return False
|
|
||||||
return "samples" in frame
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeConfig:
|
|
||||||
"""Handle the fetching of configuration from the config file."""
|
|
||||||
|
|
||||||
def __init__(self, config):
|
|
||||||
"""Initialize the configuration."""
|
|
||||||
self._config = config
|
|
||||||
self._should_poll = config.get("poll", True)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name given to the entity."""
|
|
||||||
return self._config["name"]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def address(self):
|
|
||||||
"""Return the address of the device.
|
|
||||||
|
|
||||||
If an address has been provided, unhexlify it, otherwise return None
|
|
||||||
as we're talking to our local XBee device.
|
|
||||||
"""
|
|
||||||
if (address := self._config.get("address")) is not None:
|
|
||||||
return unhexlify(address)
|
|
||||||
return address
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""Return the polling state."""
|
|
||||||
return self._should_poll
|
|
||||||
|
|
||||||
|
|
||||||
class XBeePinConfig(XBeeConfig):
|
|
||||||
"""Handle the fetching of configuration from the configuration file."""
|
|
||||||
|
|
||||||
@property
|
|
||||||
def pin(self):
|
|
||||||
"""Return the GPIO pin number."""
|
|
||||||
return self._config["pin"]
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeDigitalInConfig(XBeePinConfig):
|
|
||||||
"""A subclass of XBeePinConfig."""
|
|
||||||
|
|
||||||
def __init__(self, config):
|
|
||||||
"""Initialise the XBee Zigbee Digital input config."""
|
|
||||||
super().__init__(config)
|
|
||||||
self._bool2state, self._state2bool = self.boolean_maps
|
|
||||||
|
|
||||||
@property
|
|
||||||
def boolean_maps(self):
|
|
||||||
"""Create mapping dictionaries for potential inversion of booleans.
|
|
||||||
|
|
||||||
Create dicts to map the pin state (true/false) to potentially inverted
|
|
||||||
values depending on the on_state config value which should be set to
|
|
||||||
"low" or "high".
|
|
||||||
"""
|
|
||||||
if self._config.get("on_state", "").lower() == "low":
|
|
||||||
bool2state = {True: False, False: True}
|
|
||||||
else:
|
|
||||||
bool2state = {True: True, False: False}
|
|
||||||
state2bool = {v: k for k, v in bool2state.items()}
|
|
||||||
return bool2state, state2bool
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bool2state(self):
|
|
||||||
"""Return a dictionary mapping the internal value to the Zigbee value.
|
|
||||||
|
|
||||||
For the translation of on/off as being pin high or low.
|
|
||||||
"""
|
|
||||||
return self._bool2state
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state2bool(self):
|
|
||||||
"""Return a dictionary mapping the Zigbee value to the internal value.
|
|
||||||
|
|
||||||
For the translation of pin high/low as being on or off.
|
|
||||||
"""
|
|
||||||
return self._state2bool
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeDigitalOutConfig(XBeePinConfig):
|
|
||||||
"""A subclass of XBeePinConfig.
|
|
||||||
|
|
||||||
Set _should_poll to default as False instead of True. The value will
|
|
||||||
still be overridden by the presence of a 'poll' config entry.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, config):
|
|
||||||
"""Initialize the XBee Zigbee Digital out."""
|
|
||||||
super().__init__(config)
|
|
||||||
self._bool2state, self._state2bool = self.boolean_maps
|
|
||||||
self._should_poll = config.get("poll", False)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def boolean_maps(self):
|
|
||||||
"""Create dicts to map booleans to pin high/low and vice versa.
|
|
||||||
|
|
||||||
Depends on the config item "on_state" which should be set to "low"
|
|
||||||
or "high".
|
|
||||||
"""
|
|
||||||
if self._config.get("on_state", "").lower() == "low":
|
|
||||||
bool2state = {
|
|
||||||
True: xb_const.GPIO_DIGITAL_OUTPUT_LOW,
|
|
||||||
False: xb_const.GPIO_DIGITAL_OUTPUT_HIGH,
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
bool2state = {
|
|
||||||
True: xb_const.GPIO_DIGITAL_OUTPUT_HIGH,
|
|
||||||
False: xb_const.GPIO_DIGITAL_OUTPUT_LOW,
|
|
||||||
}
|
|
||||||
state2bool = {v: k for k, v in bool2state.items()}
|
|
||||||
return bool2state, state2bool
|
|
||||||
|
|
||||||
@property
|
|
||||||
def bool2state(self):
|
|
||||||
"""Return a dictionary mapping booleans to GPIOSetting objects.
|
|
||||||
|
|
||||||
For the translation of on/off as being pin high or low.
|
|
||||||
"""
|
|
||||||
return self._bool2state
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state2bool(self):
|
|
||||||
"""Return a dictionary mapping GPIOSetting objects to booleans.
|
|
||||||
|
|
||||||
For the translation of pin high/low as being on or off.
|
|
||||||
"""
|
|
||||||
return self._state2bool
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeAnalogInConfig(XBeePinConfig):
|
|
||||||
"""Representation of a XBee Zigbee GPIO pin set to analog in."""
|
|
||||||
|
|
||||||
@property
|
|
||||||
def max_voltage(self):
|
|
||||||
"""Return the voltage for ADC to report its highest value."""
|
|
||||||
return float(self._config.get("max_volts", DEFAULT_ADC_MAX_VOLTS))
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeDigitalIn(Entity):
|
|
||||||
"""Representation of a GPIO pin configured as a digital input."""
|
|
||||||
|
|
||||||
def __init__(self, config, device):
|
|
||||||
"""Initialize the device."""
|
|
||||||
self._config = config
|
|
||||||
self._device = device
|
|
||||||
self._state = False
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
|
||||||
"""Register callbacks."""
|
|
||||||
|
|
||||||
def handle_frame(frame):
|
|
||||||
"""Handle an incoming frame.
|
|
||||||
|
|
||||||
Handle an incoming frame and update our status if it contains
|
|
||||||
information relating to this device.
|
|
||||||
"""
|
|
||||||
if not frame_is_relevant(self, frame):
|
|
||||||
return
|
|
||||||
sample = next(iter(frame["samples"]))
|
|
||||||
pin_name = xb_const.DIGITAL_PINS[self._config.pin]
|
|
||||||
if pin_name not in sample:
|
|
||||||
# Doesn't contain information about our pin
|
|
||||||
return
|
|
||||||
# Set state to the value of sample, respecting any inversion
|
|
||||||
# logic from the on_state config variable.
|
|
||||||
self._state = self._config.state2bool[
|
|
||||||
self._config.bool2state[sample[pin_name]]
|
|
||||||
]
|
|
||||||
self.schedule_update_ha_state()
|
|
||||||
|
|
||||||
async_dispatcher_connect(self.hass, SIGNAL_XBEE_FRAME_RECEIVED, handle_frame)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name of the input."""
|
|
||||||
return self._config.name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def config(self):
|
|
||||||
"""Return the entity's configuration."""
|
|
||||||
return self._config
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""Return the state of the polling, if needed."""
|
|
||||||
return self._config.should_poll
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_on(self):
|
|
||||||
"""Return True if the Entity is on, else False."""
|
|
||||||
return self._state
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Ask the Zigbee device what state its input pin is in."""
|
|
||||||
try:
|
|
||||||
sample = self._device.get_sample(self._config.address)
|
|
||||||
except ZigBeeTxFailure:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Transmission failure when attempting to get sample from "
|
|
||||||
"Zigbee device at address: %s",
|
|
||||||
hexlify(self._config.address),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
except ZigBeeException as exc:
|
|
||||||
_LOGGER.exception("Unable to get sample from Zigbee device: %s", exc)
|
|
||||||
return
|
|
||||||
pin_name = xb_const.DIGITAL_PINS[self._config.pin]
|
|
||||||
if pin_name not in sample:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Pin %s (%s) was not in the sample provided by Zigbee device %s",
|
|
||||||
self._config.pin,
|
|
||||||
pin_name,
|
|
||||||
hexlify(self._config.address),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
self._state = self._config.state2bool[sample[pin_name]]
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeDigitalOut(XBeeDigitalIn):
|
|
||||||
"""Representation of a GPIO pin configured as a digital input."""
|
|
||||||
|
|
||||||
def _set_state(self, state):
|
|
||||||
"""Initialize the XBee Zigbee digital out device."""
|
|
||||||
try:
|
|
||||||
self._device.set_gpio_pin(
|
|
||||||
self._config.pin, self._config.bool2state[state], self._config.address
|
|
||||||
)
|
|
||||||
except ZigBeeTxFailure:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Transmission failure when attempting to set output pin on "
|
|
||||||
"Zigbee device at address: %s",
|
|
||||||
hexlify(self._config.address),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
except ZigBeeException as exc:
|
|
||||||
_LOGGER.exception("Unable to set digital pin on XBee device: %s", exc)
|
|
||||||
return
|
|
||||||
self._state = state
|
|
||||||
if not self.should_poll:
|
|
||||||
self.schedule_update_ha_state()
|
|
||||||
|
|
||||||
def turn_on(self, **kwargs):
|
|
||||||
"""Set the digital output to its 'on' state."""
|
|
||||||
self._set_state(True)
|
|
||||||
|
|
||||||
def turn_off(self, **kwargs):
|
|
||||||
"""Set the digital output to its 'off' state."""
|
|
||||||
self._set_state(False)
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Ask the XBee device what its output is set to."""
|
|
||||||
try:
|
|
||||||
pin_state = self._device.get_gpio_pin(
|
|
||||||
self._config.pin, self._config.address
|
|
||||||
)
|
|
||||||
except ZigBeeTxFailure:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Transmission failure when attempting to get output pin status"
|
|
||||||
" from Zigbee device at address: %s",
|
|
||||||
hexlify(self._config.address),
|
|
||||||
)
|
|
||||||
return
|
|
||||||
except ZigBeeException as exc:
|
|
||||||
_LOGGER.exception(
|
|
||||||
"Unable to get output pin status from XBee device: %s", exc
|
|
||||||
)
|
|
||||||
return
|
|
||||||
self._state = self._config.state2bool[pin_state]
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeAnalogIn(SensorEntity):
|
|
||||||
"""Representation of a GPIO pin configured as an analog input."""
|
|
||||||
|
|
||||||
_attr_native_unit_of_measurement = PERCENTAGE
|
|
||||||
|
|
||||||
def __init__(self, config, device):
|
|
||||||
"""Initialize the XBee analog in device."""
|
|
||||||
self._config = config
|
|
||||||
self._device = device
|
|
||||||
self._value = None
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
|
||||||
"""Register callbacks."""
|
|
||||||
|
|
||||||
def handle_frame(frame):
|
|
||||||
"""Handle an incoming frame.
|
|
||||||
|
|
||||||
Handle an incoming frame and update our status if it contains
|
|
||||||
information relating to this device.
|
|
||||||
"""
|
|
||||||
if not frame_is_relevant(self, frame):
|
|
||||||
return
|
|
||||||
sample = frame["samples"].pop()
|
|
||||||
pin_name = xb_const.ANALOG_PINS[self._config.pin]
|
|
||||||
if pin_name not in sample:
|
|
||||||
# Doesn't contain information about our pin
|
|
||||||
return
|
|
||||||
self._value = convert_adc(
|
|
||||||
sample[pin_name], xb_const.ADC_PERCENTAGE, self._config.max_voltage
|
|
||||||
)
|
|
||||||
self.schedule_update_ha_state()
|
|
||||||
|
|
||||||
async_dispatcher_connect(self.hass, SIGNAL_XBEE_FRAME_RECEIVED, handle_frame)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name of the input."""
|
|
||||||
return self._config.name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def config(self):
|
|
||||||
"""Return the entity's configuration."""
|
|
||||||
return self._config
|
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""Return the polling state, if needed."""
|
|
||||||
return self._config.should_poll
|
|
||||||
|
|
||||||
@property
|
|
||||||
def sensor_state(self):
|
|
||||||
"""Return the state of the entity."""
|
|
||||||
return self._value
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Get the latest reading from the ADC."""
|
|
||||||
try:
|
|
||||||
self._value = self._device.read_analog_pin(
|
|
||||||
self._config.pin,
|
|
||||||
self._config.max_voltage,
|
|
||||||
self._config.address,
|
|
||||||
xb_const.ADC_PERCENTAGE,
|
|
||||||
)
|
|
||||||
except ZigBeeTxFailure:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Transmission failure when attempting to get sample from "
|
|
||||||
"Zigbee device at address: %s",
|
|
||||||
hexlify(self._config.address),
|
|
||||||
)
|
|
||||||
except ZigBeeException as exc:
|
|
||||||
_LOGGER.exception("Unable to get sample from Zigbee device: %s", exc)
|
|
@ -1,29 +0,0 @@
|
|||||||
"""Support for Zigbee binary sensors."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|
||||||
|
|
||||||
from . import PLATFORM_SCHEMA, XBeeDigitalIn, XBeeDigitalInConfig
|
|
||||||
from .const import CONF_ON_STATE, DOMAIN, STATES
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({vol.Optional(CONF_ON_STATE): vol.In(STATES)})
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
config: ConfigType,
|
|
||||||
add_entities: AddEntitiesCallback,
|
|
||||||
discovery_info: DiscoveryInfoType | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Set up the XBee Zigbee binary sensor platform."""
|
|
||||||
zigbee_device = hass.data[DOMAIN]
|
|
||||||
add_entities([XBeeBinarySensor(XBeeDigitalInConfig(config), zigbee_device)], True)
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeBinarySensor(XBeeDigitalIn, BinarySensorEntity):
|
|
||||||
"""Use XBeeDigitalIn as binary sensor."""
|
|
@ -1,5 +0,0 @@
|
|||||||
"""Constants for the xbee integration."""
|
|
||||||
CONF_ON_STATE = "on_state"
|
|
||||||
DEFAULT_ON_STATE = "high"
|
|
||||||
DOMAIN = "xbee"
|
|
||||||
STATES = ["high", "low"]
|
|
@ -1,34 +0,0 @@
|
|||||||
"""Support for XBee Zigbee lights."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.components.light import ColorMode, LightEntity
|
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|
||||||
|
|
||||||
from . import PLATFORM_SCHEMA, XBeeDigitalOut, XBeeDigitalOutConfig
|
|
||||||
from .const import CONF_ON_STATE, DEFAULT_ON_STATE, DOMAIN, STATES
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|
||||||
{vol.Optional(CONF_ON_STATE, default=DEFAULT_ON_STATE): vol.In(STATES)}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
config: ConfigType,
|
|
||||||
add_entities: AddEntitiesCallback,
|
|
||||||
discovery_info: DiscoveryInfoType | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Create and add an entity based on the configuration."""
|
|
||||||
zigbee_device = hass.data[DOMAIN]
|
|
||||||
add_entities([XBeeLight(XBeeDigitalOutConfig(config), zigbee_device)])
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeLight(XBeeDigitalOut, LightEntity):
|
|
||||||
"""Use XBeeDigitalOut as light."""
|
|
||||||
|
|
||||||
_attr_color_mode = ColorMode.ONOFF
|
|
||||||
_attr_supported_color_modes = {ColorMode.ONOFF}
|
|
@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"disabled": "Integration library not compatible with Python 3.10",
|
|
||||||
"domain": "xbee",
|
|
||||||
"name": "XBee",
|
|
||||||
"documentation": "https://www.home-assistant.io/integrations/xbee",
|
|
||||||
"requirements": ["xbee-helper==0.0.7"],
|
|
||||||
"codeowners": [],
|
|
||||||
"iot_class": "local_polling",
|
|
||||||
"loggers": ["xbee_helper"]
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
"""Support for XBee Zigbee sensors."""
|
|
||||||
# pylint: disable=import-error
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from binascii import hexlify
|
|
||||||
import logging
|
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
from xbee_helper.exceptions import ZigBeeException, ZigBeeTxFailure
|
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
|
||||||
from homeassistant.const import CONF_TYPE, TEMP_CELSIUS
|
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|
||||||
|
|
||||||
from . import DOMAIN, PLATFORM_SCHEMA, XBeeAnalogIn, XBeeAnalogInConfig, XBeeConfig
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
CONF_MAX_VOLTS = "max_volts"
|
|
||||||
|
|
||||||
DEFAULT_VOLTS = 1.2
|
|
||||||
TYPES = ["analog", "temperature"]
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|
||||||
{
|
|
||||||
vol.Required(CONF_TYPE): vol.In(TYPES),
|
|
||||||
vol.Optional(CONF_MAX_VOLTS, default=DEFAULT_VOLTS): vol.Coerce(float),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
config: ConfigType,
|
|
||||||
add_entities: AddEntitiesCallback,
|
|
||||||
discovery_info: DiscoveryInfoType | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Set up the XBee Zigbee platform.
|
|
||||||
|
|
||||||
Uses the 'type' config value to work out which type of Zigbee sensor we're
|
|
||||||
dealing with and instantiates the relevant classes to handle it.
|
|
||||||
"""
|
|
||||||
zigbee_device = hass.data[DOMAIN]
|
|
||||||
typ = config[CONF_TYPE]
|
|
||||||
|
|
||||||
try:
|
|
||||||
sensor_class, config_class = TYPE_CLASSES[typ]
|
|
||||||
except KeyError:
|
|
||||||
_LOGGER.exception("Unknown XBee Zigbee sensor type: %s", typ)
|
|
||||||
return
|
|
||||||
|
|
||||||
add_entities([sensor_class(config_class(config), zigbee_device)], True)
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeTemperatureSensor(SensorEntity):
|
|
||||||
"""Representation of XBee Pro temperature sensor."""
|
|
||||||
|
|
||||||
_attr_device_class = SensorDeviceClass.TEMPERATURE
|
|
||||||
_attr_native_unit_of_measurement = TEMP_CELSIUS
|
|
||||||
|
|
||||||
def __init__(self, config, device):
|
|
||||||
"""Initialize the sensor."""
|
|
||||||
self._config = config
|
|
||||||
self._device = device
|
|
||||||
self._temp = None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def name(self):
|
|
||||||
"""Return the name of the sensor."""
|
|
||||||
return self._config.name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_value(self):
|
|
||||||
"""Return the state of the sensor."""
|
|
||||||
return self._temp
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
"""Get the latest data."""
|
|
||||||
try:
|
|
||||||
self._temp = self._device.get_temperature(self._config.address)
|
|
||||||
except ZigBeeTxFailure:
|
|
||||||
_LOGGER.warning(
|
|
||||||
"Transmission failure when attempting to get sample from "
|
|
||||||
"Zigbee device at address: %s",
|
|
||||||
hexlify(self._config.address),
|
|
||||||
)
|
|
||||||
except ZigBeeException as exc:
|
|
||||||
_LOGGER.exception("Unable to get sample from Zigbee device: %s", exc)
|
|
||||||
|
|
||||||
|
|
||||||
# This must be below the classes to which it refers.
|
|
||||||
TYPE_CLASSES = {
|
|
||||||
"temperature": (XBeeTemperatureSensor, XBeeConfig),
|
|
||||||
"analog": (XBeeAnalogIn, XBeeAnalogInConfig),
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
"""Support for XBee Zigbee switches."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity
|
|
||||||
from homeassistant.core import HomeAssistant
|
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
|
||||||
|
|
||||||
from . import PLATFORM_SCHEMA, XBeeDigitalOut, XBeeDigitalOutConfig
|
|
||||||
from .const import CONF_ON_STATE, DOMAIN, STATES
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({vol.Optional(CONF_ON_STATE): vol.In(STATES)})
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
config: ConfigType,
|
|
||||||
add_entities: AddEntitiesCallback,
|
|
||||||
discovery_info: DiscoveryInfoType | None = None,
|
|
||||||
) -> None:
|
|
||||||
"""Set up the XBee Zigbee switch platform."""
|
|
||||||
zigbee_device = hass.data[DOMAIN]
|
|
||||||
add_entities([XBeeSwitch(XBeeDigitalOutConfig(config), zigbee_device)])
|
|
||||||
|
|
||||||
|
|
||||||
class XBeeSwitch(XBeeDigitalOut, SwitchEntity):
|
|
||||||
"""Representation of a XBee Zigbee Digital Out device."""
|
|
Loading…
x
Reference in New Issue
Block a user