Binary sensors for netgear_lte (#22902)

* Binary sensors for netgear_lte

* Move LTEEntity to component

* Revert unrelated manifest changes

* Address review comments

* Remove unused import
This commit is contained in:
Anders Melchiorsen 2019-04-09 20:28:20 +02:00 committed by GitHub
parent 4803f319b6
commit 58ec77b017
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 136 additions and 58 deletions

View File

@ -11,16 +11,20 @@ from homeassistant.const import (
CONF_HOST, CONF_MONITORED_CONDITIONS, CONF_NAME, CONF_PASSWORD, CONF_HOST, CONF_MONITORED_CONDITIONS, CONF_NAME, CONF_PASSWORD,
CONF_RECIPIENT, EVENT_HOMEASSISTANT_STOP) CONF_RECIPIENT, EVENT_HOMEASSISTANT_STOP)
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.components.binary_sensor import (
DOMAIN as BINARY_SENSOR_DOMAIN)
from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN from homeassistant.components.notify import DOMAIN as NOTIFY_DOMAIN
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
from homeassistant.helpers import config_validation as cv, discovery from homeassistant.helpers import config_validation as cv, discovery
from homeassistant.helpers.aiohttp_client import async_create_clientsession from homeassistant.helpers.aiohttp_client import async_create_clientsession
from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.dispatcher import (
async_dispatcher_send, async_dispatcher_connect)
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.event import async_track_time_interval
from . import sensor_types from . import sensor_types
REQUIREMENTS = ['eternalegypt==0.0.6'] REQUIREMENTS = ['eternalegypt==0.0.7']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -47,8 +51,15 @@ NOTIFY_SCHEMA = vol.Schema({
}) })
SENSOR_SCHEMA = vol.Schema({ SENSOR_SCHEMA = vol.Schema({
vol.Optional(CONF_MONITORED_CONDITIONS, default=sensor_types.DEFAULT): vol.Optional(CONF_MONITORED_CONDITIONS,
vol.All(cv.ensure_list, [vol.In(sensor_types.ALL)]), default=sensor_types.DEFAULT_SENSORS):
vol.All(cv.ensure_list, [vol.In(sensor_types.ALL_SENSORS)]),
})
BINARY_SENSOR_SCHEMA = vol.Schema({
vol.Optional(CONF_MONITORED_CONDITIONS,
default=sensor_types.DEFAULT_BINARY_SENSORS):
vol.All(cv.ensure_list, [vol.In(sensor_types.ALL_BINARY_SENSORS)]),
}) })
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
@ -59,6 +70,8 @@ CONFIG_SCHEMA = vol.Schema({
vol.All(cv.ensure_list, [NOTIFY_SCHEMA]), vol.All(cv.ensure_list, [NOTIFY_SCHEMA]),
vol.Optional(SENSOR_DOMAIN, default={}): vol.Optional(SENSOR_DOMAIN, default={}):
SENSOR_SCHEMA, SENSOR_SCHEMA,
vol.Optional(BINARY_SENSOR_DOMAIN, default={}):
BINARY_SENSOR_SCHEMA,
})]) })])
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
@ -160,6 +173,15 @@ async def async_setup(hass, config):
hass.async_create_task(discovery.async_load_platform( hass.async_create_task(discovery.async_load_platform(
hass, SENSOR_DOMAIN, DOMAIN, discovery_info, config)) hass, SENSOR_DOMAIN, DOMAIN, discovery_info, config))
# Binary Sensor
binary_sensor_conf = lte_conf.get(BINARY_SENSOR_DOMAIN)
discovery_info = {
CONF_HOST: lte_conf[CONF_HOST],
BINARY_SENSOR_DOMAIN: binary_sensor_conf,
}
hass.async_create_task(discovery.async_load_platform(
hass, BINARY_SENSOR_DOMAIN, DOMAIN, discovery_info, config))
return True return True
@ -239,3 +261,48 @@ async def _retry_login(hass, modem_data, password):
await _login(hass, modem_data, password) await _login(hass, modem_data, password)
except eternalegypt.Error: except eternalegypt.Error:
delay = min(2*delay, 300) delay = min(2*delay, 300)
@attr.s
class LTEEntity(Entity):
"""Base LTE entity."""
modem_data = attr.ib()
sensor_type = attr.ib()
_unique_id = attr.ib(init=False)
@_unique_id.default
def _init_unique_id(self):
"""Register unique_id while we know data is valid."""
return "{}_{}".format(
self.sensor_type, self.modem_data.data.serial_number)
async def async_added_to_hass(self):
"""Register callback."""
async_dispatcher_connect(
self.hass, DISPATCHER_NETGEAR_LTE, self.async_write_ha_state)
async def async_update(self):
"""Force update of state."""
await self.modem_data.async_update()
@property
def should_poll(self):
"""Return that the sensor should not be polled."""
return False
@property
def available(self):
"""Return the availability of the sensor."""
return self.modem_data.data is not None
@property
def unique_id(self):
"""Return a unique ID like 'usage_5TG365AB0078V'."""
return self._unique_id
@property
def name(self):
"""Return the name of the sensor."""
return "Netgear LTE {}".format(self.sensor_type)

View File

@ -0,0 +1,47 @@
"""Support for Netgear LTE binary sensors."""
import logging
from homeassistant.components.binary_sensor import DOMAIN, BinarySensorDevice
from homeassistant.exceptions import PlatformNotReady
from . import CONF_MONITORED_CONDITIONS, DATA_KEY, LTEEntity
from .sensor_types import BINARY_SENSOR_CLASSES
DEPENDENCIES = ['netgear_lte']
_LOGGER = logging.getLogger(__name__)
async def async_setup_platform(
hass, config, async_add_entities, discovery_info):
"""Set up Netgear LTE binary sensor devices."""
if discovery_info is None:
return
modem_data = hass.data[DATA_KEY].get_modem_data(discovery_info)
if not modem_data or not modem_data.data:
raise PlatformNotReady
binary_sensor_conf = discovery_info[DOMAIN]
monitored_conditions = binary_sensor_conf[CONF_MONITORED_CONDITIONS]
binary_sensors = []
for sensor_type in monitored_conditions:
binary_sensors.append(LTEBinarySensor(modem_data, sensor_type))
async_add_entities(binary_sensors)
class LTEBinarySensor(LTEEntity, BinarySensorDevice):
"""Netgear LTE binary sensor entity."""
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return getattr(self.modem_data.data, self.sensor_type)
@property
def device_class(self):
"""Return the class of binary sensor."""
return BINARY_SENSOR_CLASSES[self.sensor_type]

View File

@ -3,7 +3,7 @@
"name": "Netgear lte", "name": "Netgear lte",
"documentation": "https://www.home-assistant.io/components/netgear_lte", "documentation": "https://www.home-assistant.io/components/netgear_lte",
"requirements": [ "requirements": [
"eternalegypt==0.0.6" "eternalegypt==0.0.7"
], ],
"dependencies": [], "dependencies": [],
"codeowners": [] "codeowners": []

View File

@ -1,14 +1,10 @@
"""Support for Netgear LTE sensors.""" """Support for Netgear LTE sensors."""
import logging import logging
import attr
from homeassistant.components.sensor import DOMAIN from homeassistant.components.sensor import DOMAIN
from homeassistant.exceptions import PlatformNotReady from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from . import CONF_MONITORED_CONDITIONS, DATA_KEY, DISPATCHER_NETGEAR_LTE from . import CONF_MONITORED_CONDITIONS, DATA_KEY, LTEEntity
from .sensor_types import SENSOR_SMS, SENSOR_USAGE, SENSOR_UNITS from .sensor_types import SENSOR_SMS, SENSOR_USAGE, SENSOR_UNITS
DEPENDENCIES = ['netgear_lte'] DEPENDENCIES = ['netgear_lte']
@ -42,50 +38,9 @@ async def async_setup_platform(
async_add_entities(sensors) async_add_entities(sensors)
@attr.s class LTESensor(LTEEntity):
class LTESensor(Entity):
"""Base LTE sensor entity.""" """Base LTE sensor entity."""
modem_data = attr.ib()
sensor_type = attr.ib()
_unique_id = attr.ib(init=False)
@_unique_id.default
def _init_unique_id(self):
"""Register unique_id while we know data is valid."""
return "{}_{}".format(
self.sensor_type, self.modem_data.data.serial_number)
async def async_added_to_hass(self):
"""Register callback."""
async_dispatcher_connect(
self.hass, DISPATCHER_NETGEAR_LTE, self.async_write_ha_state)
async def async_update(self):
"""Force update of state."""
await self.modem_data.async_update()
@property
def should_poll(self):
"""Return that the sensor should not be polled."""
return False
@property
def available(self):
"""Return the availability of the sensor."""
return self.modem_data.data is not None
@property
def unique_id(self):
"""Return a unique ID like 'usage_5TG365AB0078V'."""
return self._unique_id
@property
def name(self):
"""Return the name of the sensor."""
return "Netgear LTE {}".format(self.sensor_type)
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""Return the unit of measurement.""" """Return the unit of measurement."""

View File

@ -1,5 +1,7 @@
"""Define possible sensor types.""" """Define possible sensor types."""
from homeassistant.components.binary_sensor import DEVICE_CLASS_CONNECTIVITY
SENSOR_SMS = 'sms' SENSOR_SMS = 'sms'
SENSOR_USAGE = 'usage' SENSOR_USAGE = 'usage'
@ -10,17 +12,24 @@ SENSOR_UNITS = {
'rx_level': 'dBm', 'rx_level': 'dBm',
'tx_level': 'dBm', 'tx_level': 'dBm',
'upstream': None, 'upstream': None,
'wire_connected': None,
'mobile_connected': None,
'connection_text': None, 'connection_text': None,
'connection_type': None, 'connection_type': None,
'current_ps_service_type': None, 'current_ps_service_type': None,
'register_network_display': None, 'register_network_display': None,
'roaming': None,
'current_band': None, 'current_band': None,
'cell_id': None, 'cell_id': None,
} }
ALL = list(SENSOR_UNITS) BINARY_SENSOR_MOBILE_CONNECTED = 'mobile_connected'
DEFAULT = [SENSOR_USAGE] BINARY_SENSOR_CLASSES = {
'roaming': None,
'wire_connected': DEVICE_CLASS_CONNECTIVITY,
BINARY_SENSOR_MOBILE_CONNECTED: DEVICE_CLASS_CONNECTIVITY,
}
ALL_SENSORS = list(SENSOR_UNITS)
DEFAULT_SENSORS = [SENSOR_USAGE]
ALL_BINARY_SENSORS = list(BINARY_SENSOR_CLASSES)
DEFAULT_BINARY_SENSORS = [BINARY_SENSOR_MOBILE_CONNECTED]

View File

@ -398,7 +398,7 @@ ephem==3.7.6.0
epson-projector==0.1.3 epson-projector==0.1.3
# homeassistant.components.netgear_lte # homeassistant.components.netgear_lte
eternalegypt==0.0.6 eternalegypt==0.0.7
# homeassistant.components.keyboard_remote # homeassistant.components.keyboard_remote
# evdev==0.6.1 # evdev==0.6.1