mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 00:37:13 +00:00
Multiple tag managers for Wireless Sensor Tags. (#16353)
* Added support for multiple tag managers. Fixed typo for signal strength. * Corrected broken merge. * Fixed flake8/pylint error. * Improved docstring.
This commit is contained in:
parent
f43d9ba680
commit
f63dba5521
@ -14,9 +14,6 @@ from homeassistant.components.binary_sensor import (
|
|||||||
BinarySensorDevice, PLATFORM_SCHEMA)
|
BinarySensorDevice, PLATFORM_SCHEMA)
|
||||||
from homeassistant.components.wirelesstag import (
|
from homeassistant.components.wirelesstag import (
|
||||||
DOMAIN as WIRELESSTAG_DOMAIN,
|
DOMAIN as WIRELESSTAG_DOMAIN,
|
||||||
WIRELESSTAG_TYPE_13BIT, WIRELESSTAG_TYPE_WATER,
|
|
||||||
WIRELESSTAG_TYPE_ALSPRO,
|
|
||||||
WIRELESSTAG_TYPE_WEMO_DEVICE,
|
|
||||||
SIGNAL_BINARY_EVENT_UPDATE,
|
SIGNAL_BINARY_EVENT_UPDATE,
|
||||||
WirelessTagBaseSensor)
|
WirelessTagBaseSensor)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -30,7 +27,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
# On means in range, Off means out of range
|
# On means in range, Off means out of range
|
||||||
SENSOR_PRESENCE = 'presence'
|
SENSOR_PRESENCE = 'presence'
|
||||||
|
|
||||||
# On means motion detected, Off means cear
|
# On means motion detected, Off means clear
|
||||||
SENSOR_MOTION = 'motion'
|
SENSOR_MOTION = 'motion'
|
||||||
|
|
||||||
# On means open, Off means closed
|
# On means open, Off means closed
|
||||||
@ -55,49 +52,21 @@ SENSOR_LIGHT = 'light'
|
|||||||
SENSOR_MOISTURE = 'moisture'
|
SENSOR_MOISTURE = 'moisture'
|
||||||
|
|
||||||
# On means tag battery is low, Off means normal
|
# On means tag battery is low, Off means normal
|
||||||
SENSOR_BATTERY = 'low_battery'
|
SENSOR_BATTERY = 'battery'
|
||||||
|
|
||||||
# Sensor types: Name, device_class, push notification type representing 'on',
|
# Sensor types: Name, device_class, push notification type representing 'on',
|
||||||
# attr to check
|
# attr to check
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
SENSOR_PRESENCE: ['Presence', 'presence', 'is_in_range', {
|
SENSOR_PRESENCE: 'Presence',
|
||||||
"on": "oor",
|
SENSOR_MOTION: 'Motion',
|
||||||
"off": "back_in_range"
|
SENSOR_DOOR: 'Door',
|
||||||
}, 2],
|
SENSOR_COLD: 'Cold',
|
||||||
SENSOR_MOTION: ['Motion', 'motion', 'is_moved', {
|
SENSOR_HEAT: 'Heat',
|
||||||
"on": "motion_detected",
|
SENSOR_DRY: 'Too dry',
|
||||||
}, 5],
|
SENSOR_WET: 'Too wet',
|
||||||
SENSOR_DOOR: ['Door', 'door', 'is_door_open', {
|
SENSOR_LIGHT: 'Light',
|
||||||
"on": "door_opened",
|
SENSOR_MOISTURE: 'Leak',
|
||||||
"off": "door_closed"
|
SENSOR_BATTERY: 'Low Battery'
|
||||||
}, 5],
|
|
||||||
SENSOR_COLD: ['Cold', 'cold', 'is_cold', {
|
|
||||||
"on": "temp_toolow",
|
|
||||||
"off": "temp_normal"
|
|
||||||
}, 4],
|
|
||||||
SENSOR_HEAT: ['Heat', 'heat', 'is_heat', {
|
|
||||||
"on": "temp_toohigh",
|
|
||||||
"off": "temp_normal"
|
|
||||||
}, 4],
|
|
||||||
SENSOR_DRY: ['Too dry', 'dry', 'is_too_dry', {
|
|
||||||
"on": "too_dry",
|
|
||||||
"off": "cap_normal"
|
|
||||||
}, 2],
|
|
||||||
SENSOR_WET: ['Too wet', 'wet', 'is_too_humid', {
|
|
||||||
"on": "too_humid",
|
|
||||||
"off": "cap_normal"
|
|
||||||
}, 2],
|
|
||||||
SENSOR_LIGHT: ['Light', 'light', 'is_light_on', {
|
|
||||||
"on": "too_bright",
|
|
||||||
"off": "light_normal"
|
|
||||||
}, 1],
|
|
||||||
SENSOR_MOISTURE: ['Leak', 'moisture', 'is_leaking', {
|
|
||||||
"on": "water_detected",
|
|
||||||
"off": "water_dried",
|
|
||||||
}, 1],
|
|
||||||
SENSOR_BATTERY: ['Low Battery', 'battery', 'is_battery_low', {
|
|
||||||
"on": "low_battery"
|
|
||||||
}, 3]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -114,7 +83,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
sensors = []
|
sensors = []
|
||||||
tags = platform.tags
|
tags = platform.tags
|
||||||
for tag in tags.values():
|
for tag in tags.values():
|
||||||
allowed_sensor_types = WirelessTagBinarySensor.allowed_sensors(tag)
|
allowed_sensor_types = tag.supported_binary_events_types
|
||||||
for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
|
for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
|
||||||
if sensor_type in allowed_sensor_types:
|
if sensor_type in allowed_sensor_types:
|
||||||
sensors.append(WirelessTagBinarySensor(platform, tag,
|
sensors.append(WirelessTagBinarySensor(platform, tag,
|
||||||
@ -127,59 +96,21 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
class WirelessTagBinarySensor(WirelessTagBaseSensor, BinarySensorDevice):
|
class WirelessTagBinarySensor(WirelessTagBaseSensor, BinarySensorDevice):
|
||||||
"""A binary sensor implementation for WirelessTags."""
|
"""A binary sensor implementation for WirelessTags."""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def allowed_sensors(cls, tag):
|
|
||||||
"""Return list of allowed sensor types for specific tag type."""
|
|
||||||
sensors_map = {
|
|
||||||
# 13-bit tag - allows everything but not light and moisture
|
|
||||||
WIRELESSTAG_TYPE_13BIT: [
|
|
||||||
SENSOR_PRESENCE, SENSOR_BATTERY,
|
|
||||||
SENSOR_MOTION, SENSOR_DOOR,
|
|
||||||
SENSOR_COLD, SENSOR_HEAT,
|
|
||||||
SENSOR_DRY, SENSOR_WET],
|
|
||||||
|
|
||||||
# Moister/water sensor - temperature and moisture only
|
|
||||||
WIRELESSTAG_TYPE_WATER: [
|
|
||||||
SENSOR_PRESENCE, SENSOR_BATTERY,
|
|
||||||
SENSOR_COLD, SENSOR_HEAT,
|
|
||||||
SENSOR_MOISTURE],
|
|
||||||
|
|
||||||
# ALS Pro: allows everything, but not moisture
|
|
||||||
WIRELESSTAG_TYPE_ALSPRO: [
|
|
||||||
SENSOR_PRESENCE, SENSOR_BATTERY,
|
|
||||||
SENSOR_MOTION, SENSOR_DOOR,
|
|
||||||
SENSOR_COLD, SENSOR_HEAT,
|
|
||||||
SENSOR_DRY, SENSOR_WET,
|
|
||||||
SENSOR_LIGHT],
|
|
||||||
|
|
||||||
# Wemo are power switches.
|
|
||||||
WIRELESSTAG_TYPE_WEMO_DEVICE: [SENSOR_PRESENCE]
|
|
||||||
}
|
|
||||||
|
|
||||||
# allow everything if tag type is unknown
|
|
||||||
# (i just dont have full catalog of them :))
|
|
||||||
tag_type = tag.tag_type
|
|
||||||
fullset = SENSOR_TYPES.keys()
|
|
||||||
return sensors_map[tag_type] if tag_type in sensors_map else fullset
|
|
||||||
|
|
||||||
def __init__(self, api, tag, sensor_type):
|
def __init__(self, api, tag, sensor_type):
|
||||||
"""Initialize a binary sensor for a Wireless Sensor Tags."""
|
"""Initialize a binary sensor for a Wireless Sensor Tags."""
|
||||||
super().__init__(api, tag)
|
super().__init__(api, tag)
|
||||||
self._sensor_type = sensor_type
|
self._sensor_type = sensor_type
|
||||||
self._name = '{0} {1}'.format(self._tag.name,
|
self._name = '{0} {1}'.format(self._tag.name,
|
||||||
SENSOR_TYPES[self._sensor_type][0])
|
self.event.human_readable_name)
|
||||||
self._device_class = SENSOR_TYPES[self._sensor_type][1]
|
|
||||||
self._tag_attr = SENSOR_TYPES[self._sensor_type][2]
|
|
||||||
self.binary_spec = SENSOR_TYPES[self._sensor_type][3]
|
|
||||||
self.tag_id_index_template = SENSOR_TYPES[self._sensor_type][4]
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register callbacks."""
|
"""Register callbacks."""
|
||||||
tag_id = self.tag_id
|
tag_id = self.tag_id
|
||||||
event_type = self.device_class
|
event_type = self.device_class
|
||||||
|
mac = self.tag_manager_mac
|
||||||
async_dispatcher_connect(
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
SIGNAL_BINARY_EVENT_UPDATE.format(tag_id, event_type),
|
SIGNAL_BINARY_EVENT_UPDATE.format(tag_id, event_type, mac),
|
||||||
self._on_binary_event_callback)
|
self._on_binary_event_callback)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -190,7 +121,12 @@ class WirelessTagBinarySensor(WirelessTagBaseSensor, BinarySensorDevice):
|
|||||||
@property
|
@property
|
||||||
def device_class(self):
|
def device_class(self):
|
||||||
"""Return the class of the binary sensor."""
|
"""Return the class of the binary sensor."""
|
||||||
return self._device_class
|
return self._sensor_type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def event(self):
|
||||||
|
"""Binary event of tag."""
|
||||||
|
return self._tag.event[self._sensor_type]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def principal_value(self):
|
def principal_value(self):
|
||||||
@ -198,9 +134,7 @@ class WirelessTagBinarySensor(WirelessTagBaseSensor, BinarySensorDevice):
|
|||||||
|
|
||||||
Subclasses need override based on type of sensor.
|
Subclasses need override based on type of sensor.
|
||||||
"""
|
"""
|
||||||
return (
|
return STATE_ON if self.event.is_state_on else STATE_OFF
|
||||||
STATE_ON if getattr(self._tag, self._tag_attr, False)
|
|
||||||
else STATE_OFF)
|
|
||||||
|
|
||||||
def updated_state_value(self):
|
def updated_state_value(self):
|
||||||
"""Use raw princial value."""
|
"""Use raw princial value."""
|
||||||
@ -208,7 +142,7 @@ class WirelessTagBinarySensor(WirelessTagBaseSensor, BinarySensorDevice):
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _on_binary_event_callback(self, event):
|
def _on_binary_event_callback(self, event):
|
||||||
"""Update state from arrive push notification."""
|
"""Update state from arrived push notification."""
|
||||||
# state should be 'on' or 'off'
|
# state should be 'on' or 'off'
|
||||||
self._state = event.data.get('state')
|
self._state = event.data.get('state')
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
@ -15,13 +15,9 @@ from homeassistant.const import (
|
|||||||
CONF_MONITORED_CONDITIONS)
|
CONF_MONITORED_CONDITIONS)
|
||||||
from homeassistant.components.wirelesstag import (
|
from homeassistant.components.wirelesstag import (
|
||||||
DOMAIN as WIRELESSTAG_DOMAIN,
|
DOMAIN as WIRELESSTAG_DOMAIN,
|
||||||
WIRELESSTAG_TYPE_13BIT, WIRELESSTAG_TYPE_WATER,
|
|
||||||
WIRELESSTAG_TYPE_ALSPRO,
|
|
||||||
WIRELESSTAG_TYPE_WEMO_DEVICE,
|
|
||||||
SIGNAL_TAG_UPDATE,
|
SIGNAL_TAG_UPDATE,
|
||||||
WirelessTagBaseSensor)
|
WirelessTagBaseSensor)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.const import TEMP_CELSIUS
|
|
||||||
|
|
||||||
DEPENDENCIES = ['wirelesstag']
|
DEPENDENCIES = ['wirelesstag']
|
||||||
|
|
||||||
@ -32,24 +28,12 @@ SENSOR_HUMIDITY = 'humidity'
|
|||||||
SENSOR_MOISTURE = 'moisture'
|
SENSOR_MOISTURE = 'moisture'
|
||||||
SENSOR_LIGHT = 'light'
|
SENSOR_LIGHT = 'light'
|
||||||
|
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = [
|
||||||
SENSOR_TEMPERATURE: {
|
SENSOR_TEMPERATURE,
|
||||||
'unit': TEMP_CELSIUS,
|
SENSOR_HUMIDITY,
|
||||||
'attr': 'temperature'
|
SENSOR_MOISTURE,
|
||||||
},
|
SENSOR_LIGHT
|
||||||
SENSOR_HUMIDITY: {
|
]
|
||||||
'unit': '%',
|
|
||||||
'attr': 'humidity'
|
|
||||||
},
|
|
||||||
SENSOR_MOISTURE: {
|
|
||||||
'unit': '%',
|
|
||||||
'attr': 'moisture'
|
|
||||||
},
|
|
||||||
SENSOR_LIGHT: {
|
|
||||||
'unit': 'lux',
|
|
||||||
'attr': 'light'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_MONITORED_CONDITIONS, default=[]):
|
vol.Required(CONF_MONITORED_CONDITIONS, default=[]):
|
||||||
@ -64,7 +48,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
tags = platform.tags
|
tags = platform.tags
|
||||||
for tag in tags.values():
|
for tag in tags.values():
|
||||||
for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
|
for sensor_type in config.get(CONF_MONITORED_CONDITIONS):
|
||||||
if sensor_type in WirelessTagSensor.allowed_sensors(tag):
|
if sensor_type in tag.allowed_sensor_types:
|
||||||
sensors.append(WirelessTagSensor(
|
sensors.append(WirelessTagSensor(
|
||||||
platform, tag, sensor_type, hass.config))
|
platform, tag, sensor_type, hass.config))
|
||||||
|
|
||||||
@ -74,36 +58,11 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
class WirelessTagSensor(WirelessTagBaseSensor):
|
class WirelessTagSensor(WirelessTagBaseSensor):
|
||||||
"""Representation of a Sensor."""
|
"""Representation of a Sensor."""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def allowed_sensors(cls, tag):
|
|
||||||
"""Return array of allowed sensor types for tag."""
|
|
||||||
all_sensors = SENSOR_TYPES.keys()
|
|
||||||
sensors_per_tag_type = {
|
|
||||||
WIRELESSTAG_TYPE_13BIT: [
|
|
||||||
SENSOR_TEMPERATURE,
|
|
||||||
SENSOR_HUMIDITY],
|
|
||||||
WIRELESSTAG_TYPE_WATER: [
|
|
||||||
SENSOR_TEMPERATURE,
|
|
||||||
SENSOR_MOISTURE],
|
|
||||||
WIRELESSTAG_TYPE_ALSPRO: [
|
|
||||||
SENSOR_TEMPERATURE,
|
|
||||||
SENSOR_HUMIDITY,
|
|
||||||
SENSOR_LIGHT],
|
|
||||||
WIRELESSTAG_TYPE_WEMO_DEVICE: []
|
|
||||||
}
|
|
||||||
|
|
||||||
tag_type = tag.tag_type
|
|
||||||
return (
|
|
||||||
sensors_per_tag_type[tag_type] if tag_type in sensors_per_tag_type
|
|
||||||
else all_sensors)
|
|
||||||
|
|
||||||
def __init__(self, api, tag, sensor_type, config):
|
def __init__(self, api, tag, sensor_type, config):
|
||||||
"""Initialize a WirelessTag sensor."""
|
"""Initialize a WirelessTag sensor."""
|
||||||
super().__init__(api, tag)
|
super().__init__(api, tag)
|
||||||
|
|
||||||
self._sensor_type = sensor_type
|
self._sensor_type = sensor_type
|
||||||
self._tag_attr = SENSOR_TYPES[self._sensor_type]['attr']
|
|
||||||
self._unit_of_measurement = SENSOR_TYPES[self._sensor_type]['unit']
|
|
||||||
self._name = self._tag.name
|
self._name = self._tag.name
|
||||||
|
|
||||||
# I want to see entity_id as:
|
# I want to see entity_id as:
|
||||||
@ -118,7 +77,7 @@ class WirelessTagSensor(WirelessTagBaseSensor):
|
|||||||
"""Register callbacks."""
|
"""Register callbacks."""
|
||||||
async_dispatcher_connect(
|
async_dispatcher_connect(
|
||||||
self.hass,
|
self.hass,
|
||||||
SIGNAL_TAG_UPDATE.format(self.tag_id),
|
SIGNAL_TAG_UPDATE.format(self.tag_id, self.tag_manager_mac),
|
||||||
self._update_tag_info_callback)
|
self._update_tag_info_callback)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -144,33 +103,23 @@ class WirelessTagSensor(WirelessTagBaseSensor):
|
|||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
"""Return the unit of measurement."""
|
"""Return the unit of measurement."""
|
||||||
return self._unit_of_measurement
|
return self._sensor.unit
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def principal_value(self):
|
def principal_value(self):
|
||||||
"""Return sensor current value."""
|
"""Return sensor current value."""
|
||||||
return getattr(self._tag, self._tag_attr, False)
|
return self._sensor.value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _sensor(self):
|
||||||
|
"""Return tag sensor entity."""
|
||||||
|
return self._tag.sensor[self._sensor_type]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_tag_info_callback(self, event):
|
def _update_tag_info_callback(self, event):
|
||||||
"""Handle push notification sent by tag manager."""
|
"""Handle push notification sent by tag manager."""
|
||||||
if event.data.get('id') != self.tag_id:
|
|
||||||
return
|
|
||||||
|
|
||||||
_LOGGER.info("Entity to update state: %s event data: %s",
|
_LOGGER.info("Entity to update state: %s event data: %s",
|
||||||
self, event.data)
|
self, event.data)
|
||||||
new_value = self.principal_value
|
new_value = self._sensor.value_from_update_event(event.data)
|
||||||
try:
|
|
||||||
if self._sensor_type == SENSOR_TEMPERATURE:
|
|
||||||
new_value = event.data.get('temp')
|
|
||||||
elif (self._sensor_type == SENSOR_HUMIDITY or
|
|
||||||
self._sensor_type == SENSOR_MOISTURE):
|
|
||||||
new_value = event.data.get('cap')
|
|
||||||
elif self._sensor_type == SENSOR_LIGHT:
|
|
||||||
new_value = event.data.get('lux')
|
|
||||||
except Exception as error: # pylint: disable=broad-except
|
|
||||||
_LOGGER.info("Unable to update value of entity: \
|
|
||||||
%s error: %s event: %s", self, error, event)
|
|
||||||
|
|
||||||
self._state = self.decorate_value(new_value)
|
self._state = self.decorate_value(new_value)
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
@ -11,9 +11,6 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.components.wirelesstag import (
|
from homeassistant.components.wirelesstag import (
|
||||||
DOMAIN as WIRELESSTAG_DOMAIN,
|
DOMAIN as WIRELESSTAG_DOMAIN,
|
||||||
WIRELESSTAG_TYPE_13BIT, WIRELESSTAG_TYPE_WATER,
|
|
||||||
WIRELESSTAG_TYPE_ALSPRO,
|
|
||||||
WIRELESSTAG_TYPE_WEMO_DEVICE,
|
|
||||||
WirelessTagBaseSensor)
|
WirelessTagBaseSensor)
|
||||||
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice
|
from homeassistant.components.switch import PLATFORM_SCHEMA, SwitchDevice
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -53,7 +50,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
tags = platform.load_tags()
|
tags = platform.load_tags()
|
||||||
for switch_type in config.get(CONF_MONITORED_CONDITIONS):
|
for switch_type in config.get(CONF_MONITORED_CONDITIONS):
|
||||||
for _, tag in tags.items():
|
for _, tag in tags.items():
|
||||||
if switch_type in WirelessTagSwitch.allowed_switches(tag):
|
if switch_type in tag.allowed_monitoring_types:
|
||||||
switches.append(WirelessTagSwitch(platform, tag, switch_type))
|
switches.append(WirelessTagSwitch(platform, tag, switch_type))
|
||||||
|
|
||||||
add_entities(switches, True)
|
add_entities(switches, True)
|
||||||
@ -62,30 +59,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
class WirelessTagSwitch(WirelessTagBaseSensor, SwitchDevice):
|
class WirelessTagSwitch(WirelessTagBaseSensor, SwitchDevice):
|
||||||
"""A switch implementation for Wireless Sensor Tags."""
|
"""A switch implementation for Wireless Sensor Tags."""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def allowed_switches(cls, tag):
|
|
||||||
"""Return allowed switch types for wireless tag."""
|
|
||||||
all_sensors = SWITCH_TYPES.keys()
|
|
||||||
sensors_per_tag_spec = {
|
|
||||||
WIRELESSTAG_TYPE_13BIT: [
|
|
||||||
ARM_TEMPERATURE, ARM_HUMIDITY, ARM_MOTION],
|
|
||||||
WIRELESSTAG_TYPE_WATER: [
|
|
||||||
ARM_TEMPERATURE, ARM_MOISTURE],
|
|
||||||
WIRELESSTAG_TYPE_ALSPRO: [
|
|
||||||
ARM_TEMPERATURE, ARM_HUMIDITY, ARM_MOTION, ARM_LIGHT],
|
|
||||||
WIRELESSTAG_TYPE_WEMO_DEVICE: []
|
|
||||||
}
|
|
||||||
|
|
||||||
tag_type = tag.tag_type
|
|
||||||
|
|
||||||
result = (
|
|
||||||
sensors_per_tag_spec[tag_type]
|
|
||||||
if tag_type in sensors_per_tag_spec else all_sensors)
|
|
||||||
_LOGGER.info("Allowed switches: %s tag_type: %s",
|
|
||||||
str(result), tag_type)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def __init__(self, api, tag, switch_type):
|
def __init__(self, api, tag, switch_type):
|
||||||
"""Initialize a switch for Wireless Sensor Tag."""
|
"""Initialize a switch for Wireless Sensor Tag."""
|
||||||
super().__init__(api, tag)
|
super().__init__(api, tag)
|
||||||
|
@ -4,6 +4,7 @@ Wireless Sensor Tags platform support.
|
|||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/wirelesstag/
|
https://home-assistant.io/components/wirelesstag/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from requests.exceptions import HTTPError, ConnectTimeout
|
from requests.exceptions import HTTPError, ConnectTimeout
|
||||||
@ -11,17 +12,18 @@ import voluptuous as vol
|
|||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_BATTERY_LEVEL, ATTR_VOLTAGE, CONF_USERNAME, CONF_PASSWORD)
|
ATTR_BATTERY_LEVEL, ATTR_VOLTAGE, CONF_USERNAME, CONF_PASSWORD)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant import util
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.dispatcher import (
|
from homeassistant.helpers.dispatcher import (
|
||||||
dispatcher_send)
|
dispatcher_send)
|
||||||
|
|
||||||
REQUIREMENTS = ['wirelesstagpy==0.3.0']
|
REQUIREMENTS = ['wirelesstagpy==0.4.0']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# straight of signal in dBm
|
# strength of signal in dBm
|
||||||
ATTR_TAG_SIGNAL_STRAIGHT = 'signal_straight'
|
ATTR_TAG_SIGNAL_STRENGTH = 'signal_strength'
|
||||||
# indicates if tag is out of range or not
|
# indicates if tag is out of range or not
|
||||||
ATTR_TAG_OUT_OF_RANGE = 'out_of_range'
|
ATTR_TAG_OUT_OF_RANGE = 'out_of_range'
|
||||||
# number in percents from max power of tag receiver
|
# number in percents from max power of tag receiver
|
||||||
@ -34,13 +36,13 @@ NOTIFICATION_TITLE = "Wireless Sensor Tag Setup"
|
|||||||
DOMAIN = 'wirelesstag'
|
DOMAIN = 'wirelesstag'
|
||||||
DEFAULT_ENTITY_NAMESPACE = 'wirelesstag'
|
DEFAULT_ENTITY_NAMESPACE = 'wirelesstag'
|
||||||
|
|
||||||
WIRELESSTAG_TYPE_13BIT = 13
|
# template for signal - first parameter is tag_id,
|
||||||
WIRELESSTAG_TYPE_ALSPRO = 26
|
# second, tag manager mac address
|
||||||
WIRELESSTAG_TYPE_WATER = 32
|
SIGNAL_TAG_UPDATE = 'wirelesstag.tag_info_updated_{}_{}'
|
||||||
WIRELESSTAG_TYPE_WEMO_DEVICE = 82
|
|
||||||
|
|
||||||
SIGNAL_TAG_UPDATE = 'wirelesstag.tag_info_updated_{}'
|
# template for signal - tag_id, sensor type and
|
||||||
SIGNAL_BINARY_EVENT_UPDATE = 'wirelesstag.binary_event_updated_{}_{}'
|
# tag manager mac address
|
||||||
|
SIGNAL_BINARY_EVENT_UPDATE = 'wirelesstag.binary_event_updated_{}_{}_{}'
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.Schema({
|
DOMAIN: vol.Schema({
|
||||||
@ -58,6 +60,12 @@ class WirelessTagPlatform:
|
|||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.api = api
|
self.api = api
|
||||||
self.tags = {}
|
self.tags = {}
|
||||||
|
self._local_base_url = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tag_manager_macs(self):
|
||||||
|
"""Return list of tag managers mac addresses in user account."""
|
||||||
|
return self.api.mac_addresses
|
||||||
|
|
||||||
def load_tags(self):
|
def load_tags(self):
|
||||||
"""Load tags from remote server."""
|
"""Load tags from remote server."""
|
||||||
@ -69,72 +77,84 @@ class WirelessTagPlatform:
|
|||||||
func_name = 'arm_{}'.format(switch.sensor_type)
|
func_name = 'arm_{}'.format(switch.sensor_type)
|
||||||
arm_func = getattr(self.api, func_name)
|
arm_func = getattr(self.api, func_name)
|
||||||
if arm_func is not None:
|
if arm_func is not None:
|
||||||
arm_func(switch.tag_id)
|
arm_func(switch.tag_id, switch.tag_manager_mac)
|
||||||
|
|
||||||
def disarm(self, switch):
|
def disarm(self, switch):
|
||||||
"""Disarm entity sensor monitoring."""
|
"""Disarm entity sensor monitoring."""
|
||||||
func_name = 'disarm_{}'.format(switch.sensor_type)
|
func_name = 'disarm_{}'.format(switch.sensor_type)
|
||||||
disarm_func = getattr(self.api, func_name)
|
disarm_func = getattr(self.api, func_name)
|
||||||
if disarm_func is not None:
|
if disarm_func is not None:
|
||||||
disarm_func(switch.tag_id)
|
disarm_func(switch.tag_id, switch.tag_manager_mac)
|
||||||
|
|
||||||
# pylint: disable=no-self-use
|
def make_notifications(self, binary_sensors, mac):
|
||||||
def make_push_notitication(self, name, url, content):
|
"""Create configurations for push notifications."""
|
||||||
"""Create notification config."""
|
_LOGGER.info("Creating configurations for push notifications.")
|
||||||
from wirelesstagpy import NotificationConfig
|
|
||||||
return NotificationConfig(name, {
|
|
||||||
'url': url, 'verb': 'POST',
|
|
||||||
'content': content, 'disabled': False, 'nat': True})
|
|
||||||
|
|
||||||
def install_push_notifications(self, binary_sensors):
|
|
||||||
"""Set up local push notification from tag manager."""
|
|
||||||
_LOGGER.info("Registering local push notifications.")
|
|
||||||
configs = []
|
configs = []
|
||||||
|
|
||||||
binary_url = self.binary_event_callback_url
|
bi_url = self.binary_event_callback_url
|
||||||
for event in binary_sensors:
|
for bi_sensor in binary_sensors:
|
||||||
for state, name in event.binary_spec.items():
|
configs.extend(bi_sensor.event.build_notifications(bi_url, mac))
|
||||||
content = ('{"type": "' + event.device_class +
|
|
||||||
'", "id":{' + str(event.tag_id_index_template) +
|
|
||||||
'}, "state": \"' + state + '\"}')
|
|
||||||
config = self.make_push_notitication(name, binary_url, content)
|
|
||||||
configs.append(config)
|
|
||||||
|
|
||||||
content = ("{\"name\":\"{0}\",\"id\":{1},\"temp\":{2}," +
|
|
||||||
"\"cap\":{3},\"lux\":{4}}")
|
|
||||||
update_url = self.update_callback_url
|
update_url = self.update_callback_url
|
||||||
update_config = self.make_push_notitication(
|
from wirelesstagpy import NotificationConfig as NC
|
||||||
'update', update_url, content)
|
update_config = NC.make_config_for_update_event(update_url, mac)
|
||||||
configs.append(update_config)
|
|
||||||
|
|
||||||
result = self.api.install_push_notification(0, configs, True)
|
configs.append(update_config)
|
||||||
if not result:
|
return configs
|
||||||
self.hass.components.persistent_notification.create(
|
|
||||||
"Error: failed to install local push notifications<br />",
|
def install_push_notifications(self, binary_sensors):
|
||||||
title="Wireless Sensor Tag Setup Local Push Notifications",
|
"""Register local push notification from tag manager."""
|
||||||
notification_id="wirelesstag_failed_push_notification")
|
_LOGGER.info("Registering local push notifications.")
|
||||||
else:
|
for mac in self.tag_manager_macs:
|
||||||
_LOGGER.info("Installed push notifications for all tags.")
|
configs = self.make_notifications(binary_sensors, mac)
|
||||||
|
# install notifications for all tags in tag manager
|
||||||
|
# specified by mac
|
||||||
|
result = self.api.install_push_notification(0, configs, True, mac)
|
||||||
|
if not result:
|
||||||
|
self.hass.components.persistent_notification.create(
|
||||||
|
"Error: failed to install local push notifications <br />",
|
||||||
|
title="Wireless Sensor Tag Setup Local Push Notifications",
|
||||||
|
notification_id="wirelesstag_failed_push_notification")
|
||||||
|
else:
|
||||||
|
_LOGGER.info("Installed push notifications for all\
|
||||||
|
tags in %s.", mac)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def local_base_url(self):
|
||||||
|
"""Define base url of hass in local network."""
|
||||||
|
if self._local_base_url is None:
|
||||||
|
self._local_base_url = "http://{}".format(util.get_local_ip())
|
||||||
|
|
||||||
|
port = self.hass.config.api.port
|
||||||
|
if port is not None:
|
||||||
|
self._local_base_url += ':{}'.format(port)
|
||||||
|
return self._local_base_url
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def update_callback_url(self):
|
def update_callback_url(self):
|
||||||
"""Return url for local push notifications(update event)."""
|
"""Return url for local push notifications(update event)."""
|
||||||
return '{}/api/events/wirelesstag_update_tags'.format(
|
return '{}/api/events/wirelesstag_update_tags'.format(
|
||||||
self.hass.config.api.base_url)
|
self.local_base_url)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def binary_event_callback_url(self):
|
def binary_event_callback_url(self):
|
||||||
"""Return url for local push notifications(binary event)."""
|
"""Return url for local push notifications(binary event)."""
|
||||||
return '{}/api/events/wirelesstag_binary_event'.format(
|
return '{}/api/events/wirelesstag_binary_event'.format(
|
||||||
self.hass.config.api.base_url)
|
self.local_base_url)
|
||||||
|
|
||||||
def handle_update_tags_event(self, event):
|
def handle_update_tags_event(self, event):
|
||||||
"""Handle push event from wireless tag manager."""
|
"""Handle push event from wireless tag manager."""
|
||||||
_LOGGER.info("push notification for update arrived: %s", event)
|
_LOGGER.info("push notification for update arrived: %s", event)
|
||||||
dispatcher_send(
|
try:
|
||||||
self.hass,
|
tag_id = event.data.get('id')
|
||||||
SIGNAL_TAG_UPDATE.format(event.data.get('id')),
|
mac = event.data.get('mac')
|
||||||
event)
|
dispatcher_send(
|
||||||
|
self.hass,
|
||||||
|
SIGNAL_TAG_UPDATE.format(tag_id, mac),
|
||||||
|
event)
|
||||||
|
except Exception as ex: # pylint: disable=broad-except
|
||||||
|
_LOGGER.error("Unable to handle tag update event:\
|
||||||
|
%s error: %s", str(event), str(ex))
|
||||||
|
|
||||||
def handle_binary_event(self, event):
|
def handle_binary_event(self, event):
|
||||||
"""Handle push notifications for binary (on/off) events."""
|
"""Handle push notifications for binary (on/off) events."""
|
||||||
@ -142,12 +162,13 @@ class WirelessTagPlatform:
|
|||||||
try:
|
try:
|
||||||
tag_id = event.data.get('id')
|
tag_id = event.data.get('id')
|
||||||
event_type = event.data.get('type')
|
event_type = event.data.get('type')
|
||||||
|
mac = event.data.get('mac')
|
||||||
dispatcher_send(
|
dispatcher_send(
|
||||||
self.hass,
|
self.hass,
|
||||||
SIGNAL_BINARY_EVENT_UPDATE.format(tag_id, event_type),
|
SIGNAL_BINARY_EVENT_UPDATE.format(tag_id, event_type, mac),
|
||||||
event)
|
event)
|
||||||
except Exception as ex: # pylint: disable=broad-except
|
except Exception as ex: # pylint: disable=broad-except
|
||||||
_LOGGER.error("Unable to handle binary event:\
|
_LOGGER.error("Unable to handle tag binary event:\
|
||||||
%s error: %s", str(event), str(ex))
|
%s error: %s", str(event), str(ex))
|
||||||
|
|
||||||
|
|
||||||
@ -193,6 +214,7 @@ class WirelessTagBaseSensor(Entity):
|
|||||||
self._tag = tag
|
self._tag = tag
|
||||||
self._uuid = self._tag.uuid
|
self._uuid = self._tag.uuid
|
||||||
self.tag_id = self._tag.tag_id
|
self.tag_id = self._tag.tag_id
|
||||||
|
self.tag_manager_mac = self._tag.tag_manager_mac
|
||||||
self._name = self._tag.name
|
self._name = self._tag.name
|
||||||
self._state = None
|
self._state = None
|
||||||
|
|
||||||
@ -251,8 +273,8 @@ class WirelessTagBaseSensor(Entity):
|
|||||||
return {
|
return {
|
||||||
ATTR_BATTERY_LEVEL: self._tag.battery_remaining,
|
ATTR_BATTERY_LEVEL: self._tag.battery_remaining,
|
||||||
ATTR_VOLTAGE: '{:.2f}V'.format(self._tag.battery_volts),
|
ATTR_VOLTAGE: '{:.2f}V'.format(self._tag.battery_volts),
|
||||||
ATTR_TAG_SIGNAL_STRAIGHT: '{}dBm'.format(
|
ATTR_TAG_SIGNAL_STRENGTH: '{}dBm'.format(
|
||||||
self._tag.signal_straight),
|
self._tag.signal_strength),
|
||||||
ATTR_TAG_OUT_OF_RANGE: not self._tag.is_in_range,
|
ATTR_TAG_OUT_OF_RANGE: not self._tag.is_in_range,
|
||||||
ATTR_TAG_POWER_CONSUMPTION: '{:.2f}%'.format(
|
ATTR_TAG_POWER_CONSUMPTION: '{:.2f}%'.format(
|
||||||
self._tag.power_consumption)
|
self._tag.power_consumption)
|
||||||
|
@ -1485,7 +1485,7 @@ websocket-client==0.37.0
|
|||||||
websockets==6.0
|
websockets==6.0
|
||||||
|
|
||||||
# homeassistant.components.wirelesstag
|
# homeassistant.components.wirelesstag
|
||||||
wirelesstagpy==0.3.0
|
wirelesstagpy==0.4.0
|
||||||
|
|
||||||
# homeassistant.components.zigbee
|
# homeassistant.components.zigbee
|
||||||
xbee-helper==0.0.7
|
xbee-helper==0.0.7
|
||||||
|
Loading…
x
Reference in New Issue
Block a user