Skip to content

Commit a3e785e

Browse files
committed
Add create and delete services for input number helpers
1 parent 2dd6dc2 commit a3e785e

3 files changed

Lines changed: 205 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
"""Spook - Your homie."""
2+
3+
from __future__ import annotations
4+
5+
import asyncio
6+
from typing import TYPE_CHECKING
7+
8+
import voluptuous as vol
9+
10+
from homeassistant.components.input_number import (
11+
CONF_INITIAL,
12+
CONF_MAX,
13+
CONF_MIN,
14+
CONF_STEP,
15+
DOMAIN,
16+
MODE_BOX,
17+
MODE_SLIDER,
18+
NumberStorageCollection,
19+
_cv_input_number,
20+
)
21+
from homeassistant.const import CONF_ICON, CONF_MODE, CONF_NAME, CONF_UNIT_OF_MEASUREMENT
22+
from homeassistant.exceptions import HomeAssistantError
23+
from homeassistant.helpers import config_validation as cv
24+
25+
from ....services import AbstractSpookAdminService
26+
27+
if TYPE_CHECKING:
28+
from homeassistant.core import ServiceCall
29+
30+
CONF_OBJECT_ID = "object_id"
31+
32+
CREATE_FIELDS = {
33+
vol.Required(CONF_NAME): vol.All(str, vol.Length(min=1)),
34+
vol.Optional(CONF_OBJECT_ID): cv.slug,
35+
vol.Optional(CONF_MIN, default=0): vol.Coerce(float),
36+
vol.Optional(CONF_MAX, default=100): vol.Coerce(float),
37+
vol.Optional(CONF_INITIAL): vol.Coerce(float),
38+
vol.Optional(CONF_STEP, default=1): vol.All(vol.Coerce(float), vol.Range(min=1e-9)),
39+
vol.Optional(CONF_ICON): cv.icon,
40+
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
41+
vol.Optional(CONF_MODE, default=MODE_SLIDER): vol.In([MODE_SLIDER, MODE_BOX]),
42+
}
43+
44+
45+
class SpookService(AbstractSpookAdminService):
46+
"""Input number service to create a new helper on the fly."""
47+
48+
domain = DOMAIN
49+
service = "create"
50+
schema = vol.All(vol.Schema(CREATE_FIELDS), _cv_input_number)
51+
52+
async def async_handle_service(self, call: ServiceCall) -> None:
53+
"""Handle the service call."""
54+
object_id = call.data.get(CONF_OBJECT_ID)
55+
data = {k: v for k, v in call.data.items() if k != CONF_OBJECT_ID}
56+
57+
collection: NumberStorageCollection = self.hass.data["websocket_api"][
58+
"input_number/list"
59+
][0].__self__.storage_collection
60+
61+
if object_id:
62+
async with self.hass.data.setdefault(
63+
f"{DOMAIN}_create_lock", asyncio.Lock()
64+
):
65+
if collection.id_manager.has_id(object_id):
66+
message = f"An input number with object ID '{object_id}' already exists"
67+
raise HomeAssistantError(message)
68+
collection._get_suggested_id = lambda info: object_id # noqa: SLF001
69+
try:
70+
await collection.async_create_item(data)
71+
finally:
72+
del collection._get_suggested_id # noqa: SLF001
73+
else:
74+
await collection.async_create_item(data)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""Spook - Your homie."""
2+
3+
from __future__ import annotations
4+
5+
from typing import TYPE_CHECKING
6+
7+
from homeassistant.components.input_number import (
8+
DOMAIN,
9+
InputNumber,
10+
NumberStorageCollection,
11+
)
12+
from homeassistant.exceptions import HomeAssistantError
13+
14+
from ....services import AbstractSpookEntityComponentService
15+
16+
if TYPE_CHECKING:
17+
from homeassistant.core import ServiceCall
18+
19+
20+
class SpookService(AbstractSpookEntityComponentService[InputNumber]):
21+
"""Input number service to delete a helper on the fly."""
22+
23+
domain = DOMAIN
24+
service = "delete"
25+
schema = {}
26+
27+
async def async_handle_service(
28+
self,
29+
entity: InputNumber,
30+
call: ServiceCall,
31+
) -> None:
32+
"""Handle the service call."""
33+
if not entity.editable:
34+
message = f"This input number is not editable: {entity.entity_id}"
35+
raise HomeAssistantError(message)
36+
37+
collection: NumberStorageCollection = self.hass.data["websocket_api"][
38+
"input_number/list"
39+
][0].__self__.storage_collection
40+
await collection.async_delete_item(entity.unique_id)

custom_components/spook/services.yaml

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,97 @@ input_number_min:
956956
entity:
957957
domain: input_number
958958

959+
input_number_create:
960+
name: Create an input number 👻
961+
description: >-
962+
Create a new input number helper on the fly.
963+
fields:
964+
name:
965+
name: Name
966+
description: The name of the new input number helper.
967+
required: true
968+
selector:
969+
text:
970+
object_id:
971+
name: Object ID
972+
description: >-
973+
The object ID for the new input number helper. If not provided, the
974+
object ID will be generated based on the name.
975+
required: false
976+
selector:
977+
text:
978+
min:
979+
name: Minimum
980+
description: The minimum value of the input number.
981+
required: false
982+
default: 0
983+
selector:
984+
number:
985+
mode: box
986+
step: any
987+
max:
988+
name: Maximum
989+
description: The maximum value of the input number.
990+
required: false
991+
default: 100
992+
selector:
993+
number:
994+
mode: box
995+
step: any
996+
initial:
997+
name: Initial value
998+
description: The initial value of the input number when Home Assistant starts.
999+
required: false
1000+
selector:
1001+
number:
1002+
mode: box
1003+
step: any
1004+
step:
1005+
name: Step size
1006+
description: The step size of the input number.
1007+
required: false
1008+
default: 1
1009+
selector:
1010+
number:
1011+
mode: box
1012+
step: any
1013+
mode:
1014+
name: Display mode
1015+
description: >-
1016+
The display mode of the input number, which can be either a slider or
1017+
an input box.
1018+
required: false
1019+
default: slider
1020+
selector:
1021+
select:
1022+
options:
1023+
- label: Slider
1024+
value: slider
1025+
- label: Input field
1026+
value: box
1027+
icon:
1028+
name: Icon
1029+
description: The icon to use for the input number helper.
1030+
required: false
1031+
selector:
1032+
icon:
1033+
unit_of_measurement:
1034+
name: Unit of measurement
1035+
description: The unit of measurement of the input number.
1036+
required: false
1037+
selector:
1038+
text:
1039+
1040+
input_number_delete:
1041+
name: Delete an input number 👻
1042+
description: >-
1043+
Delete an input number helper. This works only with input numbers created
1044+
and managed via the UI. Input numbers created and managed in YAML cannot
1045+
be managed by Spook.
1046+
target:
1047+
entity:
1048+
domain: input_number
1049+
9591050
person_add_device_tracker:
9601051
name: Add a device tracker 👻
9611052
description: >-

0 commit comments

Comments
 (0)