mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add ElkM1 time and counter services and keypress event (#41867)
This commit is contained in:
parent
a0bb8ae5d9
commit
801168f9d7
@ -19,12 +19,16 @@ from homeassistant.const import (
|
|||||||
TEMP_FAHRENHEIT,
|
TEMP_FAHRENHEIT,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
|
ATTR_KEY,
|
||||||
|
ATTR_KEY_NAME,
|
||||||
|
ATTR_KEYPAD_ID,
|
||||||
BARE_TEMP_CELSIUS,
|
BARE_TEMP_CELSIUS,
|
||||||
BARE_TEMP_FAHRENHEIT,
|
BARE_TEMP_FAHRENHEIT,
|
||||||
CONF_AREA,
|
CONF_AREA,
|
||||||
@ -41,6 +45,7 @@ from .const import (
|
|||||||
CONF_ZONE,
|
CONF_ZONE,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
ELK_ELEMENTS,
|
ELK_ELEMENTS,
|
||||||
|
EVENT_ELKM1_KEYPAD_KEY_PRESSED,
|
||||||
)
|
)
|
||||||
|
|
||||||
SYNC_TIMEOUT = 120
|
SYNC_TIMEOUT = 120
|
||||||
@ -63,6 +68,12 @@ SPEAK_SERVICE_SCHEMA = vol.Schema(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SET_TIME_SERVICE_SCHEMA = vol.Schema(
|
||||||
|
{
|
||||||
|
vol.Optional("prefix", default=""): cv.string,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _host_validator(config):
|
def _host_validator(config):
|
||||||
"""Validate that a host is properly configured."""
|
"""Validate that a host is properly configured."""
|
||||||
@ -221,6 +232,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||||||
)
|
)
|
||||||
elk.connect()
|
elk.connect()
|
||||||
|
|
||||||
|
def _element_changed(element, changeset):
|
||||||
|
keypress = changeset.get("last_keypress")
|
||||||
|
if keypress is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
hass.bus.async_fire(
|
||||||
|
EVENT_ELKM1_KEYPAD_KEY_PRESSED,
|
||||||
|
{
|
||||||
|
ATTR_KEYPAD_ID: element.index + 1,
|
||||||
|
ATTR_KEY_NAME: keypress[0],
|
||||||
|
ATTR_KEY: keypress[1],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
for keypad in elk.keypads: # pylint: disable=no-member
|
||||||
|
keypad.add_callback(_element_changed)
|
||||||
|
|
||||||
if not await async_wait_for_elk_to_sync(elk, SYNC_TIMEOUT):
|
if not await async_wait_for_elk_to_sync(elk, SYNC_TIMEOUT):
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Timed out after %d seconds while trying to sync with ElkM1 at %s",
|
"Timed out after %d seconds while trying to sync with ElkM1 at %s",
|
||||||
@ -297,21 +325,21 @@ async def async_wait_for_elk_to_sync(elk, timeout):
|
|||||||
|
|
||||||
|
|
||||||
def _create_elk_services(hass):
|
def _create_elk_services(hass):
|
||||||
def _speak_word_service(service):
|
def _getelk(service):
|
||||||
prefix = service.data["prefix"]
|
prefix = service.data["prefix"]
|
||||||
elk = _find_elk_by_prefix(hass, prefix)
|
elk = _find_elk_by_prefix(hass, prefix)
|
||||||
if elk is None:
|
if elk is None:
|
||||||
_LOGGER.error("No elk m1 with prefix for speak_word: '%s'", prefix)
|
raise HomeAssistantError(f"No ElkM1 with prefix '{prefix}' found")
|
||||||
return
|
return elk
|
||||||
elk.panel.speak_word(service.data["number"])
|
|
||||||
|
def _speak_word_service(service):
|
||||||
|
_getelk(service).panel.speak_word(service.data["number"])
|
||||||
|
|
||||||
def _speak_phrase_service(service):
|
def _speak_phrase_service(service):
|
||||||
prefix = service.data["prefix"]
|
_getelk(service).panel.speak_phrase(service.data["number"])
|
||||||
elk = _find_elk_by_prefix(hass, prefix)
|
|
||||||
if elk is None:
|
def _set_time_service(service):
|
||||||
_LOGGER.error("No elk m1 with prefix for speak_phrase: '%s'", prefix)
|
_getelk(service).panel.set_time(dt_util.now())
|
||||||
return
|
|
||||||
elk.panel.speak_phrase(service.data["number"])
|
|
||||||
|
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
DOMAIN, "speak_word", _speak_word_service, SPEAK_SERVICE_SCHEMA
|
DOMAIN, "speak_word", _speak_word_service, SPEAK_SERVICE_SCHEMA
|
||||||
@ -319,6 +347,9 @@ def _create_elk_services(hass):
|
|||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
DOMAIN, "speak_phrase", _speak_phrase_service, SPEAK_SERVICE_SCHEMA
|
DOMAIN, "speak_phrase", _speak_phrase_service, SPEAK_SERVICE_SCHEMA
|
||||||
)
|
)
|
||||||
|
hass.services.async_register(
|
||||||
|
DOMAIN, "set_time", _set_time_service, SET_TIME_SERVICE_SCHEMA
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_elk_entities(elk_data, elk_elements, element_type, class_, entities):
|
def create_elk_entities(elk_data, elk_elements, element_type, class_, entities):
|
||||||
|
@ -36,10 +36,16 @@ ELK_ELEMENTS = {
|
|||||||
CONF_ZONE: Max.ZONES.value,
|
CONF_ZONE: Max.ZONES.value,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVENT_ELKM1_KEYPAD_KEY_PRESSED = "elkm1.keypad_key_pressed"
|
||||||
|
|
||||||
|
|
||||||
|
ATTR_KEYPAD_ID = "keypad_id"
|
||||||
|
ATTR_KEY = "key"
|
||||||
|
ATTR_KEY_NAME = "key_name"
|
||||||
ATTR_CHANGED_BY_KEYPAD = "changed_by_keypad"
|
ATTR_CHANGED_BY_KEYPAD = "changed_by_keypad"
|
||||||
ATTR_CHANGED_BY_ID = "changed_by_id"
|
ATTR_CHANGED_BY_ID = "changed_by_id"
|
||||||
ATTR_CHANGED_BY_TIME = "changed_by_time"
|
ATTR_CHANGED_BY_TIME = "changed_by_time"
|
||||||
|
ATTR_VALUE = "value"
|
||||||
|
|
||||||
ELK_USER_CODE_SERVICE_SCHEMA = {
|
ELK_USER_CODE_SERVICE_SCHEMA = {
|
||||||
vol.Required(ATTR_CODE): vol.All(vol.Coerce(int), vol.Range(0, 999999))
|
vol.Required(ATTR_CODE): vol.All(vol.Coerce(int), vol.Range(0, 999999))
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "elkm1",
|
"domain": "elkm1",
|
||||||
"name": "Elk-M1 Control",
|
"name": "Elk-M1 Control",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/elkm1",
|
"documentation": "https://www.home-assistant.io/integrations/elkm1",
|
||||||
"requirements": ["elkm1-lib==0.8.2"],
|
"requirements": ["elkm1-lib==0.8.3"],
|
||||||
"codeowners": ["@gwww", "@bdraco"],
|
"codeowners": ["@gwww", "@bdraco"],
|
||||||
"config_flow": true
|
"config_flow": true
|
||||||
}
|
}
|
||||||
|
@ -6,18 +6,25 @@ from elkm1_lib.const import (
|
|||||||
ZoneType,
|
ZoneType,
|
||||||
)
|
)
|
||||||
from elkm1_lib.util import pretty_const, username
|
from elkm1_lib.util import pretty_const, username
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import VOLT
|
from homeassistant.const import VOLT
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity_platform
|
from homeassistant.helpers import entity_platform
|
||||||
|
|
||||||
from . import ElkAttachedEntity, create_elk_entities
|
from . import ElkAttachedEntity, create_elk_entities
|
||||||
from .const import DOMAIN, ELK_USER_CODE_SERVICE_SCHEMA
|
from .const import ATTR_VALUE, DOMAIN, ELK_USER_CODE_SERVICE_SCHEMA
|
||||||
|
|
||||||
|
SERVICE_SENSOR_COUNTER_REFRESH = "sensor_counter_refresh"
|
||||||
|
SERVICE_SENSOR_COUNTER_SET = "sensor_counter_set"
|
||||||
SERVICE_SENSOR_ZONE_BYPASS = "sensor_zone_bypass"
|
SERVICE_SENSOR_ZONE_BYPASS = "sensor_zone_bypass"
|
||||||
SERVICE_SENSOR_ZONE_TRIGGER = "sensor_zone_trigger"
|
SERVICE_SENSOR_ZONE_TRIGGER = "sensor_zone_trigger"
|
||||||
UNDEFINED_TEMPATURE = -40
|
UNDEFINED_TEMPATURE = -40
|
||||||
|
|
||||||
|
ELK_SET_COUNTER_SERVICE_SCHEMA = {
|
||||||
|
vol.Required(ATTR_VALUE): vol.All(vol.Coerce(int), vol.Range(0, 65535))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
"""Create the Elk-M1 sensor platform."""
|
"""Create the Elk-M1 sensor platform."""
|
||||||
@ -33,6 +40,16 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
|
|
||||||
platform = entity_platform.current_platform.get()
|
platform = entity_platform.current_platform.get()
|
||||||
|
|
||||||
|
platform.async_register_entity_service(
|
||||||
|
SERVICE_SENSOR_COUNTER_REFRESH,
|
||||||
|
{},
|
||||||
|
"async_counter_refresh",
|
||||||
|
)
|
||||||
|
platform.async_register_entity_service(
|
||||||
|
SERVICE_SENSOR_COUNTER_SET,
|
||||||
|
ELK_SET_COUNTER_SERVICE_SCHEMA,
|
||||||
|
"async_counter_set",
|
||||||
|
)
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_SENSOR_ZONE_BYPASS,
|
SERVICE_SENSOR_ZONE_BYPASS,
|
||||||
ELK_USER_CODE_SERVICE_SCHEMA,
|
ELK_USER_CODE_SERVICE_SCHEMA,
|
||||||
@ -63,6 +80,18 @@ class ElkSensor(ElkAttachedEntity):
|
|||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
|
async def async_counter_refresh(self):
|
||||||
|
"""Refresh the value of a counter from the panel."""
|
||||||
|
if not isinstance(self, ElkCounter):
|
||||||
|
raise HomeAssistantError("supported only on ElkM1 Counter sensors")
|
||||||
|
self._element.get()
|
||||||
|
|
||||||
|
async def async_counter_set(self, value=None):
|
||||||
|
"""Set the value of a counter on the panel."""
|
||||||
|
if not isinstance(self, ElkCounter):
|
||||||
|
raise HomeAssistantError("supported only on ElkM1 Counter sensors")
|
||||||
|
self._element.set(value)
|
||||||
|
|
||||||
async def async_zone_bypass(self, code=None):
|
async def async_zone_bypass(self, code=None):
|
||||||
"""Bypass zone."""
|
"""Bypass zone."""
|
||||||
if not isinstance(self, ElkZone):
|
if not isinstance(self, ElkZone):
|
||||||
|
@ -70,6 +70,13 @@ alarm_display_message:
|
|||||||
description: Up to 16 characters of text (truncated if too long). Default blank.
|
description: Up to 16 characters of text (truncated if too long). Default blank.
|
||||||
example: the universe, and everything.
|
example: the universe, and everything.
|
||||||
|
|
||||||
|
set_time:
|
||||||
|
description: Set the time for the panel.
|
||||||
|
fields:
|
||||||
|
prefix:
|
||||||
|
description: Prefix for the panel.
|
||||||
|
example: gatehouse
|
||||||
|
|
||||||
speak_phrase:
|
speak_phrase:
|
||||||
description: Speak a phrase. See list of phrases in ElkM1 ASCII Protocol documentation.
|
description: Speak a phrase. See list of phrases in ElkM1 ASCII Protocol documentation.
|
||||||
fields:
|
fields:
|
||||||
@ -84,6 +91,23 @@ speak_word:
|
|||||||
description: Word number to speak.
|
description: Word number to speak.
|
||||||
example: 142
|
example: 142
|
||||||
|
|
||||||
|
sensor_counter_refresh:
|
||||||
|
description: Refresh the value of a counter from the panel.
|
||||||
|
fields:
|
||||||
|
entity_id:
|
||||||
|
description: Name of counter to refresh.
|
||||||
|
example: "sensor.counting_sheep"
|
||||||
|
|
||||||
|
sensor_counter_set:
|
||||||
|
description: Set the value of a counter on the panel.
|
||||||
|
fields:
|
||||||
|
entity_id:
|
||||||
|
description: Name of counter to set.
|
||||||
|
example: "sensor.test42"
|
||||||
|
value:
|
||||||
|
description: Value to set the counter to.
|
||||||
|
example: 4242
|
||||||
|
|
||||||
sensor_zone_bypass:
|
sensor_zone_bypass:
|
||||||
description: Bypass zone.
|
description: Bypass zone.
|
||||||
fields:
|
fields:
|
||||||
|
@ -541,7 +541,7 @@ elgato==0.2.0
|
|||||||
eliqonline==1.2.2
|
eliqonline==1.2.2
|
||||||
|
|
||||||
# homeassistant.components.elkm1
|
# homeassistant.components.elkm1
|
||||||
elkm1-lib==0.8.2
|
elkm1-lib==0.8.3
|
||||||
|
|
||||||
# homeassistant.components.mobile_app
|
# homeassistant.components.mobile_app
|
||||||
emoji==0.5.4
|
emoji==0.5.4
|
||||||
|
@ -281,7 +281,7 @@ eebrightbox==0.0.4
|
|||||||
elgato==0.2.0
|
elgato==0.2.0
|
||||||
|
|
||||||
# homeassistant.components.elkm1
|
# homeassistant.components.elkm1
|
||||||
elkm1-lib==0.8.2
|
elkm1-lib==0.8.3
|
||||||
|
|
||||||
# homeassistant.components.mobile_app
|
# homeassistant.components.mobile_app
|
||||||
emoji==0.5.4
|
emoji==0.5.4
|
||||||
|
Loading…
x
Reference in New Issue
Block a user