Skip to content

Commit c432b1c

Browse files
authored
Add entities for Shely cury component (home-assistant#153918)
1 parent 00955b8 commit c432b1c

File tree

10 files changed

+754
-0
lines changed

10 files changed

+754
-0
lines changed

homeassistant/components/shelly/icons.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,14 @@
5050
"valve_status": {
5151
"default": "mdi:valve"
5252
},
53+
"vial_name": {
54+
"default": "mdi:scent"
55+
},
5356
"illuminance_level": {
5457
"default": "mdi:brightness-5"
58+
},
59+
"vial_level": {
60+
"default": "mdi:bottle-tonic-outline"
5561
}
5662
},
5763
"switch": {
@@ -61,6 +67,13 @@
6167
"off": "mdi:valve-closed",
6268
"on": "mdi:valve-open"
6369
}
70+
},
71+
"cury_slot": {
72+
"default": "mdi:scent",
73+
"state": {
74+
"off": "mdi:scent-off",
75+
"on": "mdi:scent"
76+
}
6477
}
6578
}
6679
}

homeassistant/components/shelly/number.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class RpcNumberDescription(RpcEntityDescription, NumberEntityDescription):
7272
min_fn: Callable[[dict], float] | None = None
7373
step_fn: Callable[[dict], float] | None = None
7474
mode_fn: Callable[[dict], NumberMode] | None = None
75+
slot: str | None = None
7576
method: str
7677

7778

@@ -121,6 +122,22 @@ async def async_set_native_value(self, value: float) -> None:
121122
await method(self._id, value)
122123

123124

125+
class RpcCuryIntensityNumber(RpcNumber):
126+
"""Represent a RPC Cury Intensity entity."""
127+
128+
@rpc_call
129+
async def async_set_native_value(self, value: float) -> None:
130+
"""Change the value."""
131+
method = getattr(self.coordinator.device, self.entity_description.method)
132+
133+
if TYPE_CHECKING:
134+
assert method is not None
135+
136+
await method(
137+
self._id, slot=self.entity_description.slot, intensity=round(value)
138+
)
139+
140+
124141
class RpcBluTrvNumber(RpcNumber):
125142
"""Represent a RPC BluTrv number."""
126143

@@ -274,6 +291,38 @@ async def async_set_native_value(self, value: float) -> None:
274291
is True,
275292
entity_class=RpcBluTrvNumber,
276293
),
294+
"left_slot_intensity": RpcNumberDescription(
295+
key="cury",
296+
sub_key="slots",
297+
name="Left slot intensity",
298+
value=lambda status, _: status["left"]["intensity"],
299+
native_min_value=0,
300+
native_max_value=100,
301+
native_step=1,
302+
mode=NumberMode.SLIDER,
303+
native_unit_of_measurement=PERCENTAGE,
304+
method="cury_set",
305+
slot="left",
306+
available=lambda status: (left := status["left"]) is not None
307+
and left.get("vial", {}).get("level", -1) != -1,
308+
entity_class=RpcCuryIntensityNumber,
309+
),
310+
"right_slot_intensity": RpcNumberDescription(
311+
key="cury",
312+
sub_key="slots",
313+
name="Right slot intensity",
314+
value=lambda status, _: status["right"]["intensity"],
315+
native_min_value=0,
316+
native_max_value=100,
317+
native_step=1,
318+
mode=NumberMode.SLIDER,
319+
native_unit_of_measurement=PERCENTAGE,
320+
method="cury_set",
321+
slot="right",
322+
available=lambda status: (right := status["right"]) is not None
323+
and right.get("vial", {}).get("level", -1) != -1,
324+
entity_class=RpcCuryIntensityNumber,
325+
),
277326
}
278327

279328

homeassistant/components/shelly/sensor.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,6 +1658,50 @@ def __init__(
16581658
state_class=SensorStateClass.MEASUREMENT,
16591659
role="phase_info",
16601660
),
1661+
"cury_left_level": RpcSensorDescription(
1662+
key="cury",
1663+
sub_key="slots",
1664+
name="Left slot level",
1665+
translation_key="vial_level",
1666+
value=lambda status, _: status["left"]["vial"]["level"],
1667+
state_class=SensorStateClass.MEASUREMENT,
1668+
native_unit_of_measurement=PERCENTAGE,
1669+
entity_category=EntityCategory.DIAGNOSTIC,
1670+
available=lambda status: (left := status["left"]) is not None
1671+
and left.get("vial", {}).get("level", -1) != -1,
1672+
),
1673+
"cury_left_vial": RpcSensorDescription(
1674+
key="cury",
1675+
sub_key="slots",
1676+
name="Left slot vial",
1677+
translation_key="vial_name",
1678+
value=lambda status, _: status["left"]["vial"]["name"],
1679+
entity_category=EntityCategory.DIAGNOSTIC,
1680+
available=lambda status: (left := status["left"]) is not None
1681+
and left.get("vial", {}).get("level", -1) != -1,
1682+
),
1683+
"cury_right_level": RpcSensorDescription(
1684+
key="cury",
1685+
sub_key="slots",
1686+
name="Right slot level",
1687+
translation_key="vial_level",
1688+
value=lambda status, _: status["right"]["vial"]["level"],
1689+
state_class=SensorStateClass.MEASUREMENT,
1690+
native_unit_of_measurement=PERCENTAGE,
1691+
entity_category=EntityCategory.DIAGNOSTIC,
1692+
available=lambda status: (right := status["right"]) is not None
1693+
and right.get("vial", {}).get("level", -1) != -1,
1694+
),
1695+
"cury_right_vial": RpcSensorDescription(
1696+
key="cury",
1697+
sub_key="slots",
1698+
name="Right slot vial",
1699+
translation_key="vial_name",
1700+
value=lambda status, _: status["right"]["vial"]["name"],
1701+
entity_category=EntityCategory.DIAGNOSTIC,
1702+
available=lambda status: (right := status["right"]) is not None
1703+
and right.get("vial", {}).get("level", -1) != -1,
1704+
),
16611705
}
16621706

16631707

homeassistant/components/shelly/switch.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,32 @@ class RpcSwitchDescription(RpcEntityDescription, SwitchEntityDescription):
230230
entity_registry_enabled_default=False,
231231
entity_category=EntityCategory.CONFIG,
232232
),
233+
"cury_left": RpcSwitchDescription(
234+
key="cury",
235+
sub_key="slots",
236+
name="Left slot",
237+
translation_key="cury_slot",
238+
is_on=lambda status: bool(status["slots"]["left"]["on"]),
239+
method_on="cury_set",
240+
method_off="cury_set",
241+
method_params_fn=lambda id, value: (id, "left", value),
242+
entity_registry_enabled_default=True,
243+
available=lambda status: (left := status["left"]) is not None
244+
and left.get("vial", {}).get("level", -1) != -1,
245+
),
246+
"cury_right": RpcSwitchDescription(
247+
key="cury",
248+
sub_key="slots",
249+
name="Right slot",
250+
translation_key="cury_slot",
251+
is_on=lambda status: bool(status["slots"]["right"]["on"]),
252+
method_on="cury_set",
253+
method_off="cury_set",
254+
method_params_fn=lambda id, value: (id, "right", value),
255+
entity_registry_enabled_default=True,
256+
available=lambda status: (right := status["right"]) is not None
257+
and right.get("vial", {}).get("level", -1) != -1,
258+
),
233259
}
234260

235261

tests/components/shelly/snapshots/test_number.ambr

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,119 @@
115115
'state': '0',
116116
})
117117
# ---
118+
# name: test_cury_number_entity[number.test_name_left_slot_intensity-entry]
119+
EntityRegistryEntrySnapshot({
120+
'aliases': set({
121+
}),
122+
'area_id': None,
123+
'capabilities': dict({
124+
'max': 100,
125+
'min': 0,
126+
'mode': <NumberMode.SLIDER: 'slider'>,
127+
'step': 1,
128+
}),
129+
'config_entry_id': <ANY>,
130+
'config_subentry_id': <ANY>,
131+
'device_class': None,
132+
'device_id': <ANY>,
133+
'disabled_by': None,
134+
'domain': 'number',
135+
'entity_category': None,
136+
'entity_id': 'number.test_name_left_slot_intensity',
137+
'has_entity_name': True,
138+
'hidden_by': None,
139+
'icon': None,
140+
'id': <ANY>,
141+
'labels': set({
142+
}),
143+
'name': None,
144+
'options': dict({
145+
}),
146+
'original_device_class': None,
147+
'original_icon': None,
148+
'original_name': 'Left slot intensity',
149+
'platform': 'shelly',
150+
'previous_unique_id': None,
151+
'suggested_object_id': None,
152+
'supported_features': 0,
153+
'translation_key': None,
154+
'unique_id': '123456789ABC-cury:0-left_slot_intensity',
155+
'unit_of_measurement': '%',
156+
})
157+
# ---
158+
# name: test_cury_number_entity[number.test_name_left_slot_intensity-state]
159+
StateSnapshot({
160+
'attributes': ReadOnlyDict({
161+
'friendly_name': 'Test name Left slot intensity',
162+
'max': 100,
163+
'min': 0,
164+
'mode': <NumberMode.SLIDER: 'slider'>,
165+
'step': 1,
166+
'unit_of_measurement': '%',
167+
}),
168+
'context': <ANY>,
169+
'entity_id': 'number.test_name_left_slot_intensity',
170+
'last_changed': <ANY>,
171+
'last_reported': <ANY>,
172+
'last_updated': <ANY>,
173+
'state': '70',
174+
})
175+
# ---
176+
# name: test_cury_number_entity[number.test_name_right_slot_intensity-entry]
177+
EntityRegistryEntrySnapshot({
178+
'aliases': set({
179+
}),
180+
'area_id': None,
181+
'capabilities': dict({
182+
'max': 100,
183+
'min': 0,
184+
'mode': <NumberMode.SLIDER: 'slider'>,
185+
'step': 1,
186+
}),
187+
'config_entry_id': <ANY>,
188+
'config_subentry_id': <ANY>,
189+
'device_class': None,
190+
'device_id': <ANY>,
191+
'disabled_by': None,
192+
'domain': 'number',
193+
'entity_category': None,
194+
'entity_id': 'number.test_name_right_slot_intensity',
195+
'has_entity_name': True,
196+
'hidden_by': None,
197+
'icon': None,
198+
'id': <ANY>,
199+
'labels': set({
200+
}),
201+
'name': None,
202+
'options': dict({
203+
}),
204+
'original_device_class': None,
205+
'original_icon': None,
206+
'original_name': 'Right slot intensity',
207+
'platform': 'shelly',
208+
'previous_unique_id': None,
209+
'suggested_object_id': None,
210+
'supported_features': 0,
211+
'translation_key': None,
212+
'unique_id': '123456789ABC-cury:0-right_slot_intensity',
213+
'unit_of_measurement': '%',
214+
})
215+
# ---
216+
# name: test_cury_number_entity[number.test_name_right_slot_intensity-state]
217+
StateSnapshot({
218+
'attributes': ReadOnlyDict({
219+
'friendly_name': 'Test name Right slot intensity',
220+
'max': 100,
221+
'min': 0,
222+
'mode': <NumberMode.SLIDER: 'slider'>,
223+
'step': 1,
224+
'unit_of_measurement': '%',
225+
}),
226+
'context': <ANY>,
227+
'entity_id': 'number.test_name_right_slot_intensity',
228+
'last_changed': <ANY>,
229+
'last_reported': <ANY>,
230+
'last_updated': <ANY>,
231+
'state': '70',
232+
})
233+
# ---

0 commit comments

Comments
 (0)