Skip to content

Commit 1431277

Browse files
committed
Rework services again
1 parent 926ad6a commit 1431277

File tree

7 files changed

+264
-62
lines changed

7 files changed

+264
-62
lines changed

custom_components/growcube/const.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
CHANNEL_NAME = ['A', 'B', 'C', 'D']
55
CHANNEL_ID = ['a', 'b', 'c', 'd']
66
SERVICE_WATER_PLANT = "water_plant"
7-
SERVICE_SET_WATERING_MODE = "set_watering_mode"
7+
SERVICE_SET_SMART_WATERING = "set_smart_watering"
8+
SERVICE_SET_SCHEDULED_WATERING = "set_scheduled_watering"
9+
SERVICE_DELETE_WATERING = "delete_watering"
810
ARGS_CHANNEL = "channel"
911
ARGS_DURATION = "duration"
10-
ARGS_MIN_VALUE = "min_value"
11-
ARGS_MAX_VALUE = "max_value"
12+
ARGS_MIN_MOISTURE = "min_moisture"
13+
ARGS_MAX_MOISTURE = "max_moisture"
14+
ARGS_ALL_DAY = "all_day"
15+
ARGS_INTERVAL = "interval"

custom_components/growcube/coordinator.py

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
LockStateGrowcubeReport,
1616
CheckOutletLockedGrowcubeReport,
1717
)
18-
from growcube_client import WateringModeCommand, SyncTimeCommand
18+
from growcube_client import WateringModeCommand, SyncTimeCommand, PlantEndCommand, ClosePumpCommand
1919
from homeassistant.core import HomeAssistant, ServiceCall
2020
from homeassistant.exceptions import HomeAssistantError
2121
from homeassistant.const import (
@@ -312,15 +312,45 @@ async def handle_water_plant(self, channel: Channel, duration: int) -> None:
312312
)
313313
await self.client.water_plant(channel, duration)
314314

315-
async def handle_set_watering_mode(self, channel: Channel, min_value: int, max_value: int) -> None:
315+
async def handle_set_smart_watering(self, channel: Channel,
316+
all_day: bool,
317+
min_moisture: int,
318+
max_moisture: int) -> None:
316319

320+
_LOGGER.debug(
321+
"%s: Service set_smart_watering called, %s, %s, %s, %s",
322+
self.data.device_id,
323+
channel,
324+
all_day,
325+
min_moisture,
326+
max_moisture,
327+
)
328+
329+
watering_mode = WateringMode.Smart if all_day else WateringMode.SmartOutside
330+
command = WateringModeCommand(channel, watering_mode, min_moisture, max_moisture)
331+
self.client.send_command(command)
332+
333+
async def handle_set_manual_watering(self, channel: Channel, duration: int, interval: int) -> None:
317334

318-
command = WateringModeCommand(channel, WateringMode.Smart, min_value, max_value)
319335
_LOGGER.debug(
320-
"%s: Service set_watering_mode called, %s, %s, %s",
336+
"%s: Service set_manual_watering called, %s, %s, %s",
321337
self.data.device_id,
322338
channel,
323-
min_value,
324-
max_value,
339+
duration,
340+
interval,
325341
)
342+
343+
command = WateringModeCommand(channel, WateringMode.Manual, interval, duration)
344+
self.client.send_command(command)
345+
346+
async def handle_delete_watering(self, channel: Channel) -> None:
347+
348+
_LOGGER.debug(
349+
"%s: Service delete_watering called, %s,",
350+
self.data.device_id,
351+
channel
352+
)
353+
command = PlantEndCommand(channel)
354+
self.client.send_command(command)
355+
command = ClosePumpCommand(channel)
326356
self.client.send_command(command)

custom_components/growcube/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"issue_tracker": "https://github.com/jonnybergdahl/homeassistant_growcube/issues",
1212
"iot_class": "local_push",
1313
"requirements": [
14-
"growcube-client==1.2.0"
14+
"growcube-client==1.2.2"
1515
],
16-
"version": "0.11.0"
16+
"version": "0.12.0"
1717
}

custom_components/growcube/services.py

Lines changed: 137 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
from homeassistant.helpers import device_registry as dr
1111

1212
from . import GrowcubeDataCoordinator
13-
from .const import DOMAIN, CHANNEL_NAME, SERVICE_WATER_PLANT, SERVICE_SET_WATERING_MODE, ARGS_CHANNEL, ARGS_DURATION, \
14-
ARGS_MIN_VALUE, ARGS_MAX_VALUE
13+
from .const import DOMAIN, CHANNEL_NAME, SERVICE_WATER_PLANT, SERVICE_SET_SMART_WATERING, \
14+
SERVICE_SET_SCHEDULED_WATERING, SERVICE_DELETE_WATERING, \
15+
ARGS_CHANNEL, ARGS_DURATION, ARGS_MIN_MOISTURE, ARGS_MAX_MOISTURE, ARGS_ALL_DAY, ARGS_INTERVAL
1516
import logging
1617

1718
_LOGGER = logging.getLogger(__name__)
@@ -22,8 +23,14 @@ async def async_setup_services(hass):
2223
async def async_call_water_plant_service(service_call: ServiceCall) -> None:
2324
await _async_handle_water_plant(hass, service_call.data)
2425

25-
async def async_call_set_watering_mode_service(service_call: ServiceCall) -> None:
26-
await _async_handle_set_watering_mode(hass, service_call.data)
26+
async def async_call_set_smart_watering_service(service_call: ServiceCall) -> None:
27+
await _async_handle_set_smart_watering(hass, service_call.data)
28+
29+
async def async_call_set_scheduled_watering_service(service_call: ServiceCall) -> None:
30+
await _async_handle_set_scheduled_watering(hass, service_call.data)
31+
32+
async def async_call_delete_watering_service(service_call: ServiceCall) -> None:
33+
await _async_handle_delete_watering(hass, service_call.data)
2734

2835
hass.services.async_register(DOMAIN,
2936
SERVICE_WATER_PLANT,
@@ -33,27 +40,45 @@ async def async_call_set_watering_mode_service(service_call: ServiceCall) -> Non
3340
vol.Required(ATTR_DEVICE_ID): cv.string,
3441
vol.Required(ARGS_CHANNEL, default='A'): cv.string,
3542
vol.Required(ARGS_DURATION, default=5): cv.positive_int,
36-
},
43+
}
44+
))
45+
hass.services.async_register(DOMAIN,
46+
SERVICE_SET_SMART_WATERING,
47+
async_call_set_smart_watering_service,
48+
schema=vol.Schema(
49+
{
50+
vol.Required(ATTR_DEVICE_ID): cv.string,
51+
vol.Required(ARGS_CHANNEL, default='A'): cv.string,
52+
vol.Required(ARGS_ALL_DAY, default=True): cv.boolean,
53+
vol.Required(ARGS_MIN_MOISTURE, default=15): cv.positive_int,
54+
vol.Required(ARGS_MAX_MOISTURE, default=40): cv.positive_int,
55+
}
3756
))
3857
hass.services.async_register(DOMAIN,
39-
SERVICE_SET_WATERING_MODE,
40-
async_call_set_watering_mode_service,
58+
SERVICE_SET_SCHEDULED_WATERING,
59+
async_call_set_scheduled_watering_service,
60+
schema=vol.Schema(
61+
{
62+
vol.Required(ATTR_DEVICE_ID): cv.string,
63+
vol.Required(ARGS_CHANNEL, default='A'): cv.string,
64+
vol.Required(ARGS_DURATION, default=6): cv.positive_int,
65+
vol.Required(ARGS_INTERVAL, default=3): cv.positive_int,
66+
}
67+
))
68+
hass.services.async_register(DOMAIN,
69+
SERVICE_DELETE_WATERING,
70+
async_call_delete_watering_service,
4171
schema=vol.Schema(
4272
{
4373
vol.Required(ATTR_DEVICE_ID): cv.string,
4474
vol.Required(ARGS_CHANNEL, default='A'): cv.string,
45-
vol.Required(ARGS_MIN_VALUE, default=15): cv.positive_int,
46-
vol.Required(ARGS_MAX_VALUE, default=40): cv.positive_int,
4775
}
4876
))
4977

5078

5179
async def _async_handle_water_plant(hass: HomeAssistant, data: Mapping[str, Any]) -> None:
5280

53-
device_registry = dr.async_get(hass)
54-
device_entry = device_registry.async_get(data[ATTR_DEVICE_ID])
55-
device = list(device_entry.identifiers)[0][1]
56-
coordinator = _get_coordinator(hass, device)
81+
coordinator = _get_coordinator(hass, data)
5782

5883
if coordinator is None:
5984
_LOGGER.warning(f"Unable to find coordinator for {data[ATTR_DEVICE_ID]}")
@@ -97,69 +122,139 @@ async def _async_handle_water_plant(hass: HomeAssistant, data: Mapping[str, Any]
97122
await coordinator.handle_water_plant(channel, duration)
98123

99124

100-
async def _async_handle_set_watering_mode(hass: HomeAssistant, data: Mapping[str, Any]) -> None:
125+
async def _async_handle_set_smart_watering(hass: HomeAssistant, data: Mapping[str, Any]) -> None:
101126

102-
device_registry = dr.async_get(hass)
103-
device_entry = device_registry.async_get(data[ATTR_DEVICE_ID])
104-
device = list(device_entry.identifiers)[0][1]
105-
coordinator = _get_coordinator(hass, device)
127+
coordinator, device = _get_coordinator(hass, data)
106128

107129
if coordinator is None:
108130
_LOGGER.error(f"Unable to find coordinator for {device}")
109131
return
110132

111-
channel_str = data["channel"]
112-
min_value = data["min_value"]
113-
max_value = data["max_value"]
133+
channel_str = data[ARGS_CHANNEL]
134+
min_moisture = data[ARGS_MIN_MOISTURE]
135+
max_moisture = data[ARGS_MAX_MOISTURE]
136+
all_day = data[ARGS_ALL_DAY]
114137

115138
# Validate data
116139
if channel_str not in CHANNEL_NAME:
117140
_LOGGER.error(
118141
"%s: %s - Invalid channel specified: %s",
119142
device,
120-
SERVICE_SET_WATERING_MODE,
143+
SERVICE_SET_SMART_WATERING,
121144
channel_str
122145
)
123146
raise HomeAssistantError(f"Invalid channel '{channel_str}' specified")
124147

125-
if min_value <= 0 or min_value > 100:
148+
if min_moisture <= 0 or min_moisture > 100:
126149
_LOGGER.error(
127-
"%s: %s - Invalid min_value specified: %s",
150+
"%s: %s - Invalid min_moisture specified: %s",
128151
device,
129-
SERVICE_SET_WATERING_MODE,
130-
min_value
152+
SERVICE_SET_SMART_WATERING,
153+
min_moisture
131154
)
132-
raise HomeAssistantError(f"Invalid min_value '{min_value}' specified")
155+
raise HomeAssistantError(f"Invalid min_moisture '{min_moisture}' specified")
133156

134-
if max_value <= 0 or max_value > 100:
157+
if max_moisture <= 0 or max_moisture > 100:
135158
_LOGGER.error(
136-
"%s: %s - Invalid max_value specified: %s",
159+
"%s: %s - Invalid max_moisture specified: %s",
137160
device,
138-
SERVICE_SET_WATERING_MODE,
139-
max_value
161+
SERVICE_SET_SMART_WATERING,
162+
max_moisture
140163
)
141-
raise HomeAssistantError(f"Invalid max_value '{max_value}' specified")
164+
raise HomeAssistantError(f"Invalid max_moisture '{max_moisture}' specified")
142165

143-
if max_value <= min_value:
166+
if max_moisture <= min_moisture:
144167
_LOGGER.error(
145-
"%s: %s - Invalid values specified, max_value %s must be bigger than min_value %s",
168+
"%s: %s - Invalid values specified, max_moisture %s must be bigger than min_moisture %s",
146169
device,
147-
SERVICE_SET_WATERING_MODE,
148-
min_value,
149-
max_value
170+
SERVICE_SET_SMART_WATERING,
171+
min_moisture,
172+
max_moisture
150173
)
151174
raise HomeAssistantError(
152-
f"Invalid values specified, max_value {max_value}must be bigger than min_value {min_value}")
175+
f"Invalid values specified, max_moisture {max_moisture} must be bigger than min_moisture {min_moisture}")
153176

154177
channel = Channel(CHANNEL_NAME.index(channel_str))
155-
await coordinator.handle_set_watering_mode(channel, min_value, max_value)
178+
await coordinator.handle_set_smart_watering(channel, all_day, min_moisture, max_moisture)
179+
180+
181+
async def _async_handle_set_scheduled_watering(hass: HomeAssistant, data: Mapping[str, Any]) -> None:
182+
183+
coordinator, device = _get_coordinator(hass, data)
184+
185+
if coordinator is None:
186+
_LOGGER.error(f"Unable to find coordinator for {device}")
187+
return
188+
189+
channel_str = data[ARGS_CHANNEL]
190+
duration = data[ARGS_DURATION]
191+
interval = data[ARGS_INTERVAL]
156192

193+
# Validate data
194+
if channel_str not in CHANNEL_NAME:
195+
_LOGGER.error(
196+
"%s: %s - Invalid channel specified: %s",
197+
device,
198+
SERVICE_SET_SMART_WATERING,
199+
channel_str
200+
)
201+
raise HomeAssistantError(f"Invalid channel '{channel_str}' specified")
202+
203+
if duration <= 0 or duration > 100:
204+
_LOGGER.error(
205+
"%s: %s - Invalid duration specified: %s",
206+
device,
207+
SERVICE_SET_SMART_WATERING,
208+
duration
209+
)
210+
raise HomeAssistantError(f"Invalid duration '{duration}' specified")
211+
212+
if interval <= 0 or interval > 240:
213+
_LOGGER.error(
214+
"%s: %s - Invalid interval specified: %s",
215+
device,
216+
SERVICE_SET_SMART_WATERING,
217+
interval
218+
)
219+
raise HomeAssistantError(f"Invalid interval '{interval}' specified")
220+
221+
channel = Channel(CHANNEL_NAME.index(channel_str))
222+
await coordinator.handle_set_manual_watering(channel, duration, interval)
223+
224+
225+
async def _async_handle_delete_watering(hass: HomeAssistant, data: Mapping[str, Any]) -> None:
226+
227+
coordinator, device = _get_coordinator(hass, data)
228+
229+
if coordinator is None:
230+
raise HomeAssistantError(f"Unable to find coordinator for {device}")
231+
232+
channel_str = data["channel"]
233+
234+
# Validate data
235+
if channel_str not in CHANNEL_NAME:
236+
_LOGGER.error(
237+
"%s: %s - Invalid channel specified: %s",
238+
id,
239+
SERVICE_DELETE_WATERING,
240+
channel_str
241+
)
242+
raise HomeAssistantError(f"Invalid channel '{channel_str}' specified")
243+
244+
channel = Channel(CHANNEL_NAME.index(channel_str))
245+
await coordinator.handle_delete_watering(channel)
246+
247+
248+
def _get_coordinator(hass: HomeAssistant, data: Mapping[str, Any]) -> { GrowcubeDataCoordinator, str }:
249+
device_registry = dr.async_get(hass)
250+
device_id = data[ATTR_DEVICE_ID]
251+
device_entry = device_registry.async_get(device_id)
252+
device = list(device_entry.identifiers)[0][1]
157253

158-
def _get_coordinator(hass: HomeAssistant, device: str) -> GrowcubeDataCoordinator:
159254
for key in hass.data[DOMAIN]:
160255
coordinator = hass.data[DOMAIN][key]
161256
if coordinator.data.device_id == device:
162-
return coordinator
257+
return coordinator, device_id
163258

164259
_LOGGER.error("No coordinator found for %s", device)
165-
return None
260+
return None, device_id

0 commit comments

Comments
 (0)