Skip to content

Commit f4b95ff

Browse files
sresciopjbuffardRenierM26emontnemery
authored
Ezviz battery camera work mode (home-assistant#130478)
* Add support for EzViz Battery Camera work mode * feat: address review comment, add 'battery' to work mode string * feat: optimize entity addition for Ezviz select component * refactor: streamline error handling in Ezviz select actions * Update library * update library * Bump api to pin mqtt to compatable version * fix after rebase * Update code owners * codeowners * Add support for EzViz Battery Camera work mode * feat: address review comment, add 'battery' to work mode string * feat: optimize entity addition for Ezviz select component * refactor: streamline error handling in Ezviz select actions * feat: address review item simplify Ezviz select actions by removing base class and moving methods * chore: fix ruff lint * feat: check for SupportExt before adding battery select * chore: cleanup logging * feat: restored battery work mode, separated defnitions for sound and battery selects, check SupportExt with type casting * Apply suggestions from code review --------- Co-authored-by: Pierre-Jean Buffard <[email protected]> Co-authored-by: Renier Moorcroft <[email protected]> Co-authored-by: Erik Montnemery <[email protected]>
1 parent f800248 commit f4b95ff

File tree

2 files changed

+114
-24
lines changed

2 files changed

+114
-24
lines changed

homeassistant/components/ezviz/select.py

Lines changed: 104 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22

33
from __future__ import annotations
44

5+
from collections.abc import Callable
56
from dataclasses import dataclass
6-
7-
from pyezvizapi.constants import DeviceSwitchType, SoundMode
7+
from typing import cast
8+
9+
from pyezvizapi.constants import (
10+
BatteryCameraWorkMode,
11+
DeviceCatagories,
12+
DeviceSwitchType,
13+
SoundMode,
14+
SupportExt,
15+
)
816
from pyezvizapi.exceptions import HTTPError, PyEzvizError
917

1018
from homeassistant.components.select import SelectEntity, SelectEntityDescription
@@ -24,17 +32,83 @@ class EzvizSelectEntityDescription(SelectEntityDescription):
2432
"""Describe a EZVIZ Select entity."""
2533

2634
supported_switch: int
35+
current_option: Callable[[EzvizSelect], str | None]
36+
select_option: Callable[[EzvizSelect, str, str], None]
37+
38+
39+
def alarm_sound_mode_current_option(ezvizSelect: EzvizSelect) -> str | None:
40+
"""Return the selected entity option to represent the entity state."""
41+
sound_mode_value = getattr(
42+
SoundMode, ezvizSelect.data[ezvizSelect.entity_description.key]
43+
).value
44+
if sound_mode_value in [0, 1, 2]:
45+
return ezvizSelect.options[sound_mode_value]
46+
47+
return None
48+
49+
50+
def alarm_sound_mode_select_option(
51+
ezvizSelect: EzvizSelect, serial: str, option: str
52+
) -> None:
53+
"""Change the selected option."""
54+
sound_mode_value = ezvizSelect.options.index(option)
55+
ezvizSelect.coordinator.ezviz_client.alarm_sound(serial, sound_mode_value, 1)
2756

2857

29-
SELECT_TYPE = EzvizSelectEntityDescription(
58+
ALARM_SOUND_MODE_SELECT_TYPE = EzvizSelectEntityDescription(
3059
key="alarm_sound_mod",
3160
translation_key="alarm_sound_mode",
3261
entity_category=EntityCategory.CONFIG,
3362
options=["soft", "intensive", "silent"],
3463
supported_switch=DeviceSwitchType.ALARM_TONE.value,
64+
current_option=alarm_sound_mode_current_option,
65+
select_option=alarm_sound_mode_select_option,
3566
)
3667

3768

69+
def battery_work_mode_current_option(ezvizSelect: EzvizSelect) -> str | None:
70+
"""Return the selected entity option to represent the entity state."""
71+
battery_work_mode = getattr(
72+
BatteryCameraWorkMode,
73+
ezvizSelect.data[ezvizSelect.entity_description.key],
74+
BatteryCameraWorkMode.UNKNOWN,
75+
)
76+
if battery_work_mode == BatteryCameraWorkMode.UNKNOWN:
77+
return None
78+
79+
return battery_work_mode.name.lower()
80+
81+
82+
def battery_work_mode_select_option(
83+
ezvizSelect: EzvizSelect, serial: str, option: str
84+
) -> None:
85+
"""Change the selected option."""
86+
battery_work_mode = getattr(BatteryCameraWorkMode, option.upper())
87+
ezvizSelect.coordinator.ezviz_client.set_battery_camera_work_mode(
88+
serial, battery_work_mode.value
89+
)
90+
91+
92+
BATTERY_WORK_MODE_SELECT_TYPE = EzvizSelectEntityDescription(
93+
key="battery_camera_work_mode",
94+
translation_key="battery_camera_work_mode",
95+
icon="mdi:battery-sync",
96+
entity_category=EntityCategory.CONFIG,
97+
options=[
98+
"plugged_in",
99+
"high_performance",
100+
"power_save",
101+
"super_power_save",
102+
"custom",
103+
],
104+
supported_switch=-1,
105+
current_option=battery_work_mode_current_option,
106+
select_option=battery_work_mode_select_option,
107+
)
108+
109+
SELECT_TYPES = [ALARM_SOUND_MODE_SELECT_TYPE, BATTERY_WORK_MODE_SELECT_TYPE]
110+
111+
38112
async def async_setup_entry(
39113
hass: HomeAssistant,
40114
entry: EzvizConfigEntry,
@@ -43,12 +117,26 @@ async def async_setup_entry(
43117
"""Set up EZVIZ select entities based on a config entry."""
44118
coordinator = entry.runtime_data
45119

46-
async_add_entities(
47-
EzvizSelect(coordinator, camera)
120+
entities = [
121+
EzvizSelect(coordinator, camera, ALARM_SOUND_MODE_SELECT_TYPE)
48122
for camera in coordinator.data
49123
for switch in coordinator.data[camera]["switches"]
50-
if switch == SELECT_TYPE.supported_switch
51-
)
124+
if switch == ALARM_SOUND_MODE_SELECT_TYPE.supported_switch
125+
]
126+
127+
for camera in coordinator.data:
128+
device_category = coordinator.data[camera].get("device_category")
129+
supportExt = coordinator.data[camera].get("supportExt")
130+
if (
131+
device_category == DeviceCatagories.BATTERY_CAMERA_DEVICE_CATEGORY.value
132+
and supportExt
133+
and str(SupportExt.SupportBatteryManage.value) in supportExt
134+
):
135+
entities.append(
136+
EzvizSelect(coordinator, camera, BATTERY_WORK_MODE_SELECT_TYPE)
137+
)
138+
139+
async_add_entities(entities)
52140

53141

54142
class EzvizSelect(EzvizEntity, SelectEntity):
@@ -58,31 +146,23 @@ def __init__(
58146
self,
59147
coordinator: EzvizDataUpdateCoordinator,
60148
serial: str,
149+
description: EzvizSelectEntityDescription,
61150
) -> None:
62-
"""Initialize the sensor."""
151+
"""Initialize the select entity."""
63152
super().__init__(coordinator, serial)
64-
self._attr_unique_id = f"{serial}_{SELECT_TYPE.key}"
65-
self.entity_description = SELECT_TYPE
153+
self._attr_unique_id = f"{serial}_{description.key}"
154+
self.entity_description = description
66155

67156
@property
68157
def current_option(self) -> str | None:
69158
"""Return the selected entity option to represent the entity state."""
70-
sound_mode_value = getattr(
71-
SoundMode, self.data[self.entity_description.key]
72-
).value
73-
if sound_mode_value in [0, 1, 2]:
74-
return self.options[sound_mode_value]
75-
76-
return None
159+
desc = cast(EzvizSelectEntityDescription, self.entity_description)
160+
return desc.current_option(self)
77161

78162
def select_option(self, option: str) -> None:
79163
"""Change the selected option."""
80-
sound_mode_value = self.options.index(option)
81-
164+
desc = cast(EzvizSelectEntityDescription, self.entity_description)
82165
try:
83-
self.coordinator.ezviz_client.alarm_sound(self._serial, sound_mode_value, 1)
84-
166+
return desc.select_option(self, self._serial, option)
85167
except (HTTPError, PyEzvizError) as err:
86-
raise HomeAssistantError(
87-
f"Cannot set Warning sound level for {self.entity_id}"
88-
) from err
168+
raise HomeAssistantError(f"Cannot select option for {desc.key}") from err

homeassistant/components/ezviz/strings.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@
6868
"intensive": "Intensive",
6969
"silent": "Silent"
7070
}
71+
},
72+
"battery_camera_work_mode": {
73+
"name": "Battery work mode",
74+
"state": {
75+
"plugged_in": "Plugged in",
76+
"high_performance": "High performance",
77+
"power_save": "Power save",
78+
"super_power_save": "Super power saving",
79+
"custom": "Custom"
80+
}
7181
}
7282
},
7383
"image": {

0 commit comments

Comments
 (0)