Add ElkM1 time and counter services and keypress event (#41867)
parent
a0bb8ae5d9
commit
801168f9d7
|
@ -19,12 +19,16 @@ from homeassistant.const import (
|
|||
TEMP_FAHRENHEIT,
|
||||
)
|
||||
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.entity import Entity
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from .const import (
|
||||
ATTR_KEY,
|
||||
ATTR_KEY_NAME,
|
||||
ATTR_KEYPAD_ID,
|
||||
BARE_TEMP_CELSIUS,
|
||||
BARE_TEMP_FAHRENHEIT,
|
||||
CONF_AREA,
|
||||
|
@ -41,6 +45,7 @@ from .const import (
|
|||
CONF_ZONE,
|
||||
DOMAIN,
|
||||
ELK_ELEMENTS,
|
||||
EVENT_ELKM1_KEYPAD_KEY_PRESSED,
|
||||
)
|
||||
|
||||
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):
|
||||
"""Validate that a host is properly configured."""
|
||||
|
@ -221,6 +232,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
|
|||
)
|
||||
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):
|
||||
_LOGGER.error(
|
||||
"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 _speak_word_service(service):
|
||||
def _getelk(service):
|
||||
prefix = service.data["prefix"]
|
||||
elk = _find_elk_by_prefix(hass, prefix)
|
||||
if elk is None:
|
||||
_LOGGER.error("No elk m1 with prefix for speak_word: '%s'", prefix)
|
||||
return
|
||||
elk.panel.speak_word(service.data["number"])
|
||||
raise HomeAssistantError(f"No ElkM1 with prefix '{prefix}' found")
|
||||
return elk
|
||||
|
||||
def _speak_word_service(service):
|
||||
_getelk(service).panel.speak_word(service.data["number"])
|
||||
|
||||
def _speak_phrase_service(service):
|
||||
prefix = service.data["prefix"]
|
||||
elk = _find_elk_by_prefix(hass, prefix)
|
||||
if elk is None:
|
||||
_LOGGER.error("No elk m1 with prefix for speak_phrase: '%s'", prefix)
|
||||
return
|
||||
elk.panel.speak_phrase(service.data["number"])
|
||||
_getelk(service).panel.speak_phrase(service.data["number"])
|
||||
|
||||
def _set_time_service(service):
|
||||
_getelk(service).panel.set_time(dt_util.now())
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, "speak_word", _speak_word_service, SPEAK_SERVICE_SCHEMA
|
||||
|
@ -319,6 +347,9 @@ def _create_elk_services(hass):
|
|||
hass.services.async_register(
|
||||
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):
|
||||
|
|
|
@ -36,10 +36,16 @@ ELK_ELEMENTS = {
|
|||
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_ID = "changed_by_id"
|
||||
ATTR_CHANGED_BY_TIME = "changed_by_time"
|
||||
ATTR_VALUE = "value"
|
||||
|
||||
ELK_USER_CODE_SERVICE_SCHEMA = {
|
||||
vol.Required(ATTR_CODE): vol.All(vol.Coerce(int), vol.Range(0, 999999))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"domain": "elkm1",
|
||||
"name": "Elk-M1 Control",
|
||||
"documentation": "https://www.home-assistant.io/integrations/elkm1",
|
||||
"requirements": ["elkm1-lib==0.8.2"],
|
||||
"requirements": ["elkm1-lib==0.8.3"],
|
||||
"codeowners": ["@gwww", "@bdraco"],
|
||||
"config_flow": true
|
||||
}
|
||||
|
|
|
@ -6,18 +6,25 @@ from elkm1_lib.const import (
|
|||
ZoneType,
|
||||
)
|
||||
from elkm1_lib.util import pretty_const, username
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import VOLT
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_platform
|
||||
|
||||
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_TRIGGER = "sensor_zone_trigger"
|
||||
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):
|
||||
"""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.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(
|
||||
SERVICE_SENSOR_ZONE_BYPASS,
|
||||
ELK_USER_CODE_SERVICE_SCHEMA,
|
||||
|
@ -63,6 +80,18 @@ class ElkSensor(ElkAttachedEntity):
|
|||
"""Return the state of the sensor."""
|
||||
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):
|
||||
"""Bypass zone."""
|
||||
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.
|
||||
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:
|
||||
description: Speak a phrase. See list of phrases in ElkM1 ASCII Protocol documentation.
|
||||
fields:
|
||||
|
@ -84,6 +91,23 @@ speak_word:
|
|||
description: Word number to speak.
|
||||
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:
|
||||
description: Bypass zone.
|
||||
fields:
|
||||
|
|
|
@ -541,7 +541,7 @@ elgato==0.2.0
|
|||
eliqonline==1.2.2
|
||||
|
||||
# homeassistant.components.elkm1
|
||||
elkm1-lib==0.8.2
|
||||
elkm1-lib==0.8.3
|
||||
|
||||
# homeassistant.components.mobile_app
|
||||
emoji==0.5.4
|
||||
|
|
|
@ -281,7 +281,7 @@ eebrightbox==0.0.4
|
|||
elgato==0.2.0
|
||||
|
||||
# homeassistant.components.elkm1
|
||||
elkm1-lib==0.8.2
|
||||
elkm1-lib==0.8.3
|
||||
|
||||
# homeassistant.components.mobile_app
|
||||
emoji==0.5.4
|
||||
|
|
Loading…
Reference in New Issue