mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 06:47:09 +00:00
Add Elk-M1 sensor platform (#17342)
* Initial sensor version. * Add Elk-M1 sensor services. Initial version of services.yaml. * Fix lint errors. * Fix PR comments. * fix PR comment * Fix PR comment * Fix PR comments * fix
This commit is contained in:
parent
ff33cbd22f
commit
3655fefec2
@ -35,7 +35,13 @@ CONF_ENABLED = 'enabled'
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SUPPORTED_DOMAINS = ['alarm_control_panel', 'light', 'scene', 'switch']
|
||||
SUPPORTED_DOMAINS = ['alarm_control_panel', 'light', 'scene', 'sensor',
|
||||
'switch']
|
||||
|
||||
SPEAK_SERVICE_SCHEMA = vol.Schema({
|
||||
vol.Required('number'):
|
||||
vol.All(vol.Coerce(int), vol.Range(min=0, max=999))
|
||||
})
|
||||
|
||||
|
||||
def _host_validator(config):
|
||||
@ -135,6 +141,8 @@ async def async_setup(hass: HomeAssistant, hass_config: ConfigType) -> bool:
|
||||
'password': conf[CONF_PASSWORD]})
|
||||
elk.connect()
|
||||
|
||||
_create_elk_services(hass, elk)
|
||||
|
||||
hass.data[DOMAIN] = {'elk': elk, 'config': config, 'keypads': {}}
|
||||
for component in SUPPORTED_DOMAINS:
|
||||
hass.async_create_task(
|
||||
@ -143,6 +151,19 @@ async def async_setup(hass: HomeAssistant, hass_config: ConfigType) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def _create_elk_services(hass, elk):
|
||||
def _speak_word_service(service):
|
||||
elk.panel.speak_word(service.data.get('number'))
|
||||
|
||||
def _speak_phrase_service(service):
|
||||
elk.panel.speak_phrase(service.data.get('number'))
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, 'speak_word', _speak_word_service, SPEAK_SERVICE_SCHEMA)
|
||||
hass.services.async_register(
|
||||
DOMAIN, 'speak_phrase', _speak_phrase_service, SPEAK_SERVICE_SCHEMA)
|
||||
|
||||
|
||||
def create_elk_entities(hass, elk_elements, element_type, class_, entities):
|
||||
"""Create the ElkM1 devices of a particular class."""
|
||||
elk_data = hass.data[DOMAIN]
|
||||
|
12
homeassistant/components/elkm1/services.yaml
Normal file
12
homeassistant/components/elkm1/services.yaml
Normal file
@ -0,0 +1,12 @@
|
||||
speak_word:
|
||||
description: Speak a word. See list of words in ElkM1 ASCII Protocol documentation.
|
||||
fields:
|
||||
number:
|
||||
description: Word number to speak.
|
||||
example: 142
|
||||
speak_phrase:
|
||||
description: Speak a phrase. See list of phrases in ElkM1 ASCII Protocol documentation.
|
||||
fields:
|
||||
number:
|
||||
description: Phrase number to speak.
|
||||
example: 42
|
227
homeassistant/components/sensor/elkm1.py
Normal file
227
homeassistant/components/sensor/elkm1.py
Normal file
@ -0,0 +1,227 @@
|
||||
"""
|
||||
Support for control of ElkM1 sensors.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/sensor.elkm1/
|
||||
"""
|
||||
from homeassistant.components.elkm1 import (
|
||||
DOMAIN as ELK_DOMAIN, create_elk_entities, ElkEntity)
|
||||
|
||||
DEPENDENCIES = [ELK_DOMAIN]
|
||||
|
||||
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
"""Create the Elk-M1 sensor platform."""
|
||||
if discovery_info is None:
|
||||
return
|
||||
|
||||
elk = hass.data[ELK_DOMAIN]['elk']
|
||||
entities = create_elk_entities(
|
||||
hass, elk.counters, 'counter', ElkCounter, [])
|
||||
entities = create_elk_entities(
|
||||
hass, elk.keypads, 'keypad', ElkKeypad, entities)
|
||||
entities = create_elk_entities(
|
||||
hass, [elk.panel], 'panel', ElkPanel, entities)
|
||||
entities = create_elk_entities(
|
||||
hass, elk.settings, 'setting', ElkSetting, entities)
|
||||
entities = create_elk_entities(
|
||||
hass, elk.zones, 'zone', ElkZone, entities)
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
def temperature_to_state(temperature, undefined_temperature):
|
||||
"""Convert temperature to a state."""
|
||||
return temperature if temperature > undefined_temperature else None
|
||||
|
||||
|
||||
class ElkSensor(ElkEntity):
|
||||
"""Base representation of Elk-M1 sensor."""
|
||||
|
||||
def __init__(self, element, elk, elk_data):
|
||||
"""Initialize the base of all Elk sensors."""
|
||||
super().__init__(element, elk, elk_data)
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
return self._state
|
||||
|
||||
|
||||
class ElkCounter(ElkSensor):
|
||||
"""Representation of an Elk-M1 Counter."""
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend."""
|
||||
return 'mdi:numeric'
|
||||
|
||||
def _element_changed(self, element, changeset):
|
||||
self._state = self._element.value
|
||||
|
||||
|
||||
class ElkKeypad(ElkSensor):
|
||||
"""Representation of an Elk-M1 Keypad."""
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the temperature unit."""
|
||||
return self._temperature_unit
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement."""
|
||||
return self._temperature_unit
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend."""
|
||||
return 'mdi:thermometer-lines'
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Attributes of the sensor."""
|
||||
from elkm1_lib.util import username
|
||||
|
||||
attrs = self.initial_attrs()
|
||||
attrs['area'] = self._element.area + 1
|
||||
attrs['temperature'] = self._element.temperature
|
||||
attrs['last_user_time'] = self._element.last_user_time.isoformat()
|
||||
attrs['last_user'] = self._element.last_user + 1
|
||||
attrs['code'] = self._element.code
|
||||
attrs['last_user_name'] = username(self._elk, self._element.last_user)
|
||||
return attrs
|
||||
|
||||
def _element_changed(self, element, changeset):
|
||||
self._state = temperature_to_state(self._element.temperature, -40)
|
||||
|
||||
async def async_added_to_hass(self):
|
||||
"""Register callback for ElkM1 changes and update entity state."""
|
||||
await super().async_added_to_hass()
|
||||
self.hass.data[ELK_DOMAIN]['keypads'][
|
||||
self._element.index] = self.entity_id
|
||||
|
||||
|
||||
class ElkPanel(ElkSensor):
|
||||
"""Representation of an Elk-M1 Panel."""
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend."""
|
||||
return "mdi:home"
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Attributes of the sensor."""
|
||||
attrs = self.initial_attrs()
|
||||
attrs['system_trouble_status'] = self._element.system_trouble_status
|
||||
return attrs
|
||||
|
||||
def _element_changed(self, element, changeset):
|
||||
if self._elk.is_connected():
|
||||
self._state = 'Paused' if self._element.remote_programming_status \
|
||||
else 'Connected'
|
||||
else:
|
||||
self._state = 'Disconnected'
|
||||
|
||||
|
||||
class ElkSetting(ElkSensor):
|
||||
"""Representation of an Elk-M1 Setting."""
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend."""
|
||||
return 'mdi:numeric'
|
||||
|
||||
def _element_changed(self, element, changeset):
|
||||
self._state = self._element.value
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Attributes of the sensor."""
|
||||
from elkm1_lib.const import SettingFormat
|
||||
attrs = self.initial_attrs()
|
||||
attrs['value_format'] = SettingFormat(
|
||||
self._element.value_format).name.lower()
|
||||
return attrs
|
||||
|
||||
|
||||
class ElkZone(ElkSensor):
|
||||
"""Representation of an Elk-M1 Zone."""
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend."""
|
||||
from elkm1_lib.const import ZoneType
|
||||
zone_icons = {
|
||||
ZoneType.FIRE_ALARM.value: 'fire',
|
||||
ZoneType.FIRE_VERIFIED.value: 'fire',
|
||||
ZoneType.FIRE_SUPERVISORY.value: 'fire',
|
||||
ZoneType.KEYFOB.value: 'key',
|
||||
ZoneType.NON_ALARM.value: 'alarm-off',
|
||||
ZoneType.MEDICAL_ALARM.value: 'medical-bag',
|
||||
ZoneType.POLICE_ALARM.value: 'alarm-light',
|
||||
ZoneType.POLICE_NO_INDICATION.value: 'alarm-light',
|
||||
ZoneType.KEY_MOMENTARY_ARM_DISARM.value: 'power',
|
||||
ZoneType.KEY_MOMENTARY_ARM_AWAY.value: 'power',
|
||||
ZoneType.KEY_MOMENTARY_ARM_STAY.value: 'power',
|
||||
ZoneType.KEY_MOMENTARY_DISARM.value: 'power',
|
||||
ZoneType.KEY_ON_OFF.value: 'toggle-switch',
|
||||
ZoneType.MUTE_AUDIBLES.value: 'volume-mute',
|
||||
ZoneType.POWER_SUPERVISORY.value: 'power-plug',
|
||||
ZoneType.TEMPERATURE.value: 'thermometer-lines',
|
||||
ZoneType.ANALOG_ZONE.value: 'speedometer',
|
||||
ZoneType.PHONE_KEY.value: 'phone-classic',
|
||||
ZoneType.INTERCOM_KEY.value: 'deskphone'
|
||||
}
|
||||
return 'mdi:{}'.format(
|
||||
zone_icons.get(self._element.definition, 'alarm-bell'))
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Attributes of the sensor."""
|
||||
from elkm1_lib.const import (
|
||||
ZoneLogicalStatus, ZonePhysicalStatus, ZoneType)
|
||||
|
||||
attrs = self.initial_attrs()
|
||||
attrs['physical_status'] = ZonePhysicalStatus(
|
||||
self._element.physical_status).name.lower()
|
||||
attrs['logical_status'] = ZoneLogicalStatus(
|
||||
self._element.logical_status).name.lower()
|
||||
attrs['definition'] = ZoneType(
|
||||
self._element.definition).name.lower()
|
||||
attrs['area'] = self._element.area + 1
|
||||
attrs['bypassed'] = self._element.bypassed
|
||||
attrs['triggered_alarm'] = self._element.triggered_alarm
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the temperature unit."""
|
||||
from elkm1_lib.const import ZoneType
|
||||
if self._element.definition == ZoneType.TEMPERATURE.value:
|
||||
return self._temperature_unit
|
||||
return None
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement."""
|
||||
from elkm1_lib.const import ZoneType
|
||||
if self._element.definition == ZoneType.TEMPERATURE.value:
|
||||
return self._temperature_unit
|
||||
if self._element.definition == ZoneType.ANALOG_ZONE.value:
|
||||
return 'V'
|
||||
return None
|
||||
|
||||
def _element_changed(self, element, changeset):
|
||||
from elkm1_lib.const import ZoneLogicalStatus, ZoneType
|
||||
from elkm1_lib.util import pretty_const
|
||||
|
||||
if self._element.definition == ZoneType.TEMPERATURE.value:
|
||||
self._state = temperature_to_state(self._element.temperature, -60)
|
||||
elif self._element.definition == ZoneType.ANALOG_ZONE.value:
|
||||
self._state = self._element.voltage
|
||||
else:
|
||||
self._state = pretty_const(ZoneLogicalStatus(
|
||||
self._element.logical_status).name)
|
Loading…
x
Reference in New Issue
Block a user