wyzeapy 0.5.30__py3-none-any.whl → 0.5.31__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wyzeapy/__init__.py +1 -1
- wyzeapy/payload_factory.py +23 -19
- wyzeapy/services/base_service.py +73 -35
- wyzeapy/services/bulb_service.py +25 -4
- wyzeapy/services/irrigation_service.py +104 -47
- wyzeapy/tests/test_irrigation_service.py +373 -177
- wyzeapy/utils.py +14 -4
- {wyzeapy-0.5.30.dist-info → wyzeapy-0.5.31.dist-info}/METADATA +4 -4
- {wyzeapy-0.5.30.dist-info → wyzeapy-0.5.31.dist-info}/RECORD +10 -10
- {wyzeapy-0.5.30.dist-info → wyzeapy-0.5.31.dist-info}/WHEEL +1 -1
wyzeapy/__init__.py
CHANGED
|
@@ -443,7 +443,7 @@ class Wyzeapy:
|
|
|
443
443
|
if self._sensor_service is None:
|
|
444
444
|
self._sensor_service = SensorService(self._auth_lib)
|
|
445
445
|
return self._sensor_service
|
|
446
|
-
|
|
446
|
+
|
|
447
447
|
@property
|
|
448
448
|
async def irrigation_service(self) -> IrrigationService:
|
|
449
449
|
"""Returns an instance of the irrigation service"""
|
wyzeapy/payload_factory.py
CHANGED
|
@@ -51,37 +51,41 @@ def olive_create_get_payload(device_mac: str, keys: str) -> Dict[str, Any]:
|
|
|
51
51
|
|
|
52
52
|
return {"keys": keys, "did": device_mac, "nonce": nonce}
|
|
53
53
|
|
|
54
|
+
|
|
54
55
|
def olive_create_get_payload_irrigation(device_mac: str) -> Dict[str, Any]:
|
|
55
56
|
nonce = int(time.time() * 1000)
|
|
56
57
|
|
|
57
|
-
return {
|
|
58
|
-
'device_id': device_mac,
|
|
59
|
-
'nonce': str(nonce)
|
|
60
|
-
}
|
|
58
|
+
return {"device_id": device_mac, "nonce": str(nonce)}
|
|
61
59
|
|
|
62
|
-
|
|
60
|
+
|
|
61
|
+
def olive_create_post_payload_irrigation_stop(
|
|
62
|
+
device_mac: str, action: str
|
|
63
|
+
) -> Dict[str, Any]:
|
|
63
64
|
nonce = int(time.time() * 1000)
|
|
64
65
|
|
|
65
|
-
return {
|
|
66
|
-
'device_id': device_mac,
|
|
67
|
-
'nonce': str(nonce),
|
|
68
|
-
"action": action
|
|
69
|
-
}
|
|
66
|
+
return {"device_id": device_mac, "nonce": str(nonce), "action": action}
|
|
70
67
|
|
|
71
|
-
|
|
68
|
+
|
|
69
|
+
def olive_create_post_payload_irrigation_quickrun(
|
|
70
|
+
device_mac: str, zone_number: int, duration: int
|
|
71
|
+
) -> Dict[str, Any]:
|
|
72
72
|
nonce = int(time.time() * 1000)
|
|
73
73
|
|
|
74
74
|
return {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"zone_runs": [
|
|
78
|
-
{
|
|
79
|
-
"zone_number": zone_number,
|
|
80
|
-
"duration": duration
|
|
81
|
-
}
|
|
82
|
-
]
|
|
75
|
+
"device_id": device_mac,
|
|
76
|
+
"nonce": str(nonce),
|
|
77
|
+
"zone_runs": [{"zone_number": zone_number, "duration": duration}],
|
|
83
78
|
}
|
|
84
79
|
|
|
80
|
+
|
|
81
|
+
def olive_create_get_payload_irrigation_schedule_runs(
|
|
82
|
+
device_mac: str,
|
|
83
|
+
) -> Dict[str, Any]:
|
|
84
|
+
nonce = int(time.time() * 1000)
|
|
85
|
+
|
|
86
|
+
return {"device_id": device_mac, "nonce": str(nonce)}
|
|
87
|
+
|
|
88
|
+
|
|
85
89
|
def olive_create_post_payload(
|
|
86
90
|
device_mac: str, device_model: str, prop_key: str, value: Any
|
|
87
91
|
) -> Dict[str, Any]:
|
wyzeapy/services/base_service.py
CHANGED
|
@@ -39,6 +39,7 @@ from ..payload_factory import (
|
|
|
39
39
|
olive_create_get_payload_irrigation,
|
|
40
40
|
olive_create_post_payload_irrigation_stop,
|
|
41
41
|
olive_create_post_payload_irrigation_quickrun,
|
|
42
|
+
olive_create_get_payload_irrigation_schedule_runs,
|
|
42
43
|
)
|
|
43
44
|
from ..types import PropertyIDs, Device, DeviceMgmtToggleType
|
|
44
45
|
from ..utils import (
|
|
@@ -906,13 +907,13 @@ class BaseService:
|
|
|
906
907
|
payload = olive_create_get_payload_irrigation(device.mac)
|
|
907
908
|
signature = olive_create_signature(payload, self._auth_lib.token.access_token)
|
|
908
909
|
headers = {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
910
|
+
"Accept-Encoding": "gzip",
|
|
911
|
+
"User-Agent": "myapp",
|
|
912
|
+
"appid": OLIVE_APP_ID,
|
|
913
|
+
"appinfo": APP_INFO,
|
|
914
|
+
"phoneid": PHONE_ID,
|
|
915
|
+
"access_token": self._auth_lib.token.access_token,
|
|
916
|
+
"signature2": signature,
|
|
916
917
|
}
|
|
917
918
|
|
|
918
919
|
response_json = await self._auth_lib.get(url, headers=headers, params=payload)
|
|
@@ -921,50 +922,87 @@ class BaseService:
|
|
|
921
922
|
|
|
922
923
|
return response_json
|
|
923
924
|
|
|
924
|
-
|
|
925
|
-
|
|
925
|
+
async def _stop_running_schedule(
|
|
926
|
+
self, url: str, device: Device, action: str
|
|
927
|
+
) -> Dict[Any, Any]:
|
|
926
928
|
await self._auth_lib.refresh_if_should()
|
|
927
929
|
|
|
928
930
|
payload = olive_create_post_payload_irrigation_stop(device.mac, action)
|
|
929
|
-
signature = olive_create_signature(
|
|
930
|
-
|
|
931
|
+
signature = olive_create_signature(
|
|
932
|
+
json.dumps(payload, separators=(",", ":")),
|
|
933
|
+
self._auth_lib.token.access_token,
|
|
934
|
+
)
|
|
931
935
|
headers = {
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
936
|
+
"Accept-Encoding": "gzip",
|
|
937
|
+
"Content-Type": "application/json",
|
|
938
|
+
"User-Agent": "myapp",
|
|
939
|
+
"appid": OLIVE_APP_ID,
|
|
940
|
+
"appinfo": APP_INFO,
|
|
941
|
+
"phoneid": PHONE_ID,
|
|
942
|
+
"access_token": self._auth_lib.token.access_token,
|
|
943
|
+
"signature2": signature,
|
|
940
944
|
}
|
|
941
945
|
|
|
942
|
-
payload_str = json.dumps(payload, separators=(
|
|
943
|
-
response_json = await self._auth_lib.post(
|
|
946
|
+
payload_str = json.dumps(payload, separators=(",", ":"))
|
|
947
|
+
response_json = await self._auth_lib.post(
|
|
948
|
+
url, headers=headers, data=payload_str
|
|
949
|
+
)
|
|
944
950
|
|
|
945
951
|
check_for_errors_iot(self, response_json)
|
|
946
952
|
|
|
947
953
|
return response_json
|
|
948
954
|
|
|
949
|
-
async def _start_zone(
|
|
955
|
+
async def _start_zone(
|
|
956
|
+
self, url: str, device: Device, zone_number: int, duration: int
|
|
957
|
+
) -> Dict[Any, Any]:
|
|
950
958
|
await self._auth_lib.refresh_if_should()
|
|
951
959
|
|
|
952
|
-
payload = olive_create_post_payload_irrigation_quickrun(
|
|
953
|
-
|
|
954
|
-
|
|
960
|
+
payload = olive_create_post_payload_irrigation_quickrun(
|
|
961
|
+
device.mac, zone_number, duration
|
|
962
|
+
)
|
|
963
|
+
signature = olive_create_signature(
|
|
964
|
+
json.dumps(payload, separators=(",", ":")),
|
|
965
|
+
self._auth_lib.token.access_token,
|
|
966
|
+
)
|
|
955
967
|
headers = {
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
968
|
+
"Accept-Encoding": "gzip",
|
|
969
|
+
"Content-Type": "application/json",
|
|
970
|
+
"User-Agent": "myapp",
|
|
971
|
+
"appid": OLIVE_APP_ID,
|
|
972
|
+
"appinfo": APP_INFO,
|
|
973
|
+
"phoneid": PHONE_ID,
|
|
974
|
+
"access_token": self._auth_lib.token.access_token,
|
|
975
|
+
"signature2": signature,
|
|
964
976
|
}
|
|
965
977
|
|
|
966
|
-
payload_str = json.dumps(payload, separators=(
|
|
967
|
-
response_json = await self._auth_lib.post(
|
|
978
|
+
payload_str = json.dumps(payload, separators=(",", ":"))
|
|
979
|
+
response_json = await self._auth_lib.post(
|
|
980
|
+
url, headers=headers, data=payload_str
|
|
981
|
+
)
|
|
982
|
+
|
|
983
|
+
check_for_errors_iot(self, response_json)
|
|
984
|
+
|
|
985
|
+
return response_json
|
|
986
|
+
|
|
987
|
+
async def _get_schedule_runs(
|
|
988
|
+
self, url: str, device: Device, limit: int = 2
|
|
989
|
+
) -> Dict[Any, Any]:
|
|
990
|
+
await self._auth_lib.refresh_if_should()
|
|
991
|
+
|
|
992
|
+
payload = olive_create_get_payload_irrigation_schedule_runs(device.mac)
|
|
993
|
+
payload["limit"] = limit
|
|
994
|
+
signature = olive_create_signature(payload, self._auth_lib.token.access_token)
|
|
995
|
+
headers = {
|
|
996
|
+
"Accept-Encoding": "gzip",
|
|
997
|
+
"User-Agent": "myapp",
|
|
998
|
+
"appid": OLIVE_APP_ID,
|
|
999
|
+
"appinfo": APP_INFO,
|
|
1000
|
+
"phoneid": PHONE_ID,
|
|
1001
|
+
"access_token": self._auth_lib.token.access_token,
|
|
1002
|
+
"signature2": signature,
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
response_json = await self._auth_lib.get(url, headers=headers, params=payload)
|
|
968
1006
|
|
|
969
1007
|
check_for_errors_iot(self, response_json)
|
|
970
1008
|
|
wyzeapy/services/bulb_service.py
CHANGED
|
@@ -15,7 +15,20 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class Bulb(Device):
|
|
18
|
-
"""Bulb class for interacting with Wyze bulbs.
|
|
18
|
+
"""Bulb class for interacting with Wyze bulbs.
|
|
19
|
+
|
|
20
|
+
Note: When created via get_bulbs(), bulb properties (brightness, color,
|
|
21
|
+
color_temp, on) are initialized with default values. Call
|
|
22
|
+
BulbService.update(bulb) to fetch the actual current values from the
|
|
23
|
+
Wyze API.
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
bulb_service = await client.bulb_service
|
|
27
|
+
bulbs = await bulb_service.get_bulbs()
|
|
28
|
+
for bulb in bulbs:
|
|
29
|
+
bulb = await bulb_service.update(bulb) # Fetches actual values
|
|
30
|
+
print(f"Brightness: {bulb.brightness}, Color: {bulb.color}")
|
|
31
|
+
"""
|
|
19
32
|
|
|
20
33
|
_brightness: int = 0
|
|
21
34
|
_color_temp: int = 1800
|
|
@@ -90,10 +103,14 @@ class BulbService(BaseService):
|
|
|
90
103
|
"""Bulb service for interacting with Wyze bulbs."""
|
|
91
104
|
|
|
92
105
|
async def update(self, bulb: Bulb) -> Bulb:
|
|
93
|
-
"""
|
|
106
|
+
"""Fetch and update the bulb's current state from the Wyze API.
|
|
107
|
+
|
|
108
|
+
This method retrieves the actual values for brightness, color,
|
|
109
|
+
color_temp, on/off state, and other properties from the Wyze API.
|
|
110
|
+
Must be called after get_bulbs() to get accurate property values.
|
|
94
111
|
|
|
95
112
|
:param bulb: Bulb object to update
|
|
96
|
-
:return: Updated bulb object
|
|
113
|
+
:return: Updated bulb object with current property values
|
|
97
114
|
"""
|
|
98
115
|
# Get updated device_params
|
|
99
116
|
async with BaseService._update_lock:
|
|
@@ -131,7 +148,11 @@ class BulbService(BaseService):
|
|
|
131
148
|
async def get_bulbs(self) -> List[Bulb]:
|
|
132
149
|
"""Get a list of all bulbs.
|
|
133
150
|
|
|
134
|
-
:
|
|
151
|
+
Note: Returned bulbs have default property values (brightness=0,
|
|
152
|
+
color="000000", etc.). Call update(bulb) on each bulb to fetch
|
|
153
|
+
the actual current values from the Wyze API.
|
|
154
|
+
|
|
155
|
+
:return: List of Bulb objects with default property values
|
|
135
156
|
"""
|
|
136
157
|
if self._devices is None:
|
|
137
158
|
self._devices = await self.get_object_list()
|
|
@@ -42,29 +42,31 @@ class SlopeType(Enum):
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
class SoilType(Enum):
|
|
45
|
-
CLAY_LOAM =
|
|
46
|
-
CLAY =
|
|
47
|
-
SILTY_CLAY =
|
|
48
|
-
LOAM =
|
|
49
|
-
SANDY_LOAM =
|
|
50
|
-
LOAMY_SAND =
|
|
51
|
-
SAND =
|
|
45
|
+
CLAY_LOAM = "clay_loam"
|
|
46
|
+
CLAY = "clay"
|
|
47
|
+
SILTY_CLAY = "silty_clay"
|
|
48
|
+
LOAM = "loam"
|
|
49
|
+
SANDY_LOAM = "sandy_loam"
|
|
50
|
+
LOAMY_SAND = "loamy_sand"
|
|
51
|
+
SAND = "sand"
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
class Zone:
|
|
55
55
|
"""Represents a single irrigation zone."""
|
|
56
|
+
|
|
56
57
|
def __init__(self, dictionary: Dict[Any, Any]):
|
|
57
|
-
self.zone_number: int = dictionary.get(
|
|
58
|
-
self.name: str = dictionary.get(
|
|
59
|
-
self.enabled: bool = dictionary.get(
|
|
60
|
-
self.zone_id: str = dictionary.get(
|
|
61
|
-
self.smart_duration: int = dictionary.get(
|
|
62
|
-
|
|
58
|
+
self.zone_number: int = dictionary.get("zone_number", 1)
|
|
59
|
+
self.name: str = dictionary.get("name", "Zone 1")
|
|
60
|
+
self.enabled: bool = dictionary.get("enabled", True)
|
|
61
|
+
self.zone_id: str = dictionary.get("zone_id", "zone_id")
|
|
62
|
+
self.smart_duration: int = dictionary.get("smart_duration", 600)
|
|
63
|
+
|
|
63
64
|
# this quickrun duration is used only for running a zone manually
|
|
64
65
|
# the wyze api has no such value, but takes a duration as part of the api call
|
|
65
66
|
# the default value grabs the wyze smart_duration but all further updates
|
|
66
67
|
# are managed through the home assistant state
|
|
67
|
-
self.quickrun_duration: int = dictionary.get(
|
|
68
|
+
self.quickrun_duration: int = dictionary.get("smart_duration", 600)
|
|
69
|
+
|
|
68
70
|
|
|
69
71
|
class Irrigation(Device):
|
|
70
72
|
def __init__(self, dictionary: Dict[Any, Any]):
|
|
@@ -84,36 +86,40 @@ class IrrigationService(BaseService):
|
|
|
84
86
|
async def update(self, irrigation: Irrigation) -> Irrigation:
|
|
85
87
|
"""Update the irrigation device with latest data from Wyze API."""
|
|
86
88
|
# Get IoT properties
|
|
87
|
-
properties = (await self.get_iot_prop(irrigation))[
|
|
88
|
-
|
|
89
|
+
properties = (await self.get_iot_prop(irrigation))["data"]["props"]
|
|
90
|
+
|
|
89
91
|
# Update device properties
|
|
90
|
-
irrigation.RSSI = properties.get(
|
|
91
|
-
irrigation.IP = properties.get(
|
|
92
|
-
irrigation.sn = properties.get(
|
|
93
|
-
irrigation.ssid = properties.get(
|
|
94
|
-
irrigation.available = (
|
|
92
|
+
irrigation.RSSI = properties.get("RSSI", -65)
|
|
93
|
+
irrigation.IP = properties.get("IP", "192.168.1.100")
|
|
94
|
+
irrigation.sn = properties.get("sn", "SN123456789")
|
|
95
|
+
irrigation.ssid = properties.get("ssid", "ssid")
|
|
96
|
+
irrigation.available = (
|
|
97
|
+
properties.get(IrrigationProps.IOT_STATE.value) == "connected"
|
|
98
|
+
)
|
|
95
99
|
|
|
96
100
|
# Get zones
|
|
97
|
-
zones = (await self.get_zone_by_device(irrigation))[
|
|
98
|
-
|
|
101
|
+
zones = (await self.get_zone_by_device(irrigation))["data"]["zones"]
|
|
102
|
+
|
|
99
103
|
# Update zones
|
|
100
104
|
irrigation.zones = []
|
|
101
105
|
for zone in zones:
|
|
102
106
|
irrigation.zones.append(Zone(zone))
|
|
103
|
-
|
|
107
|
+
|
|
104
108
|
return irrigation
|
|
105
|
-
|
|
109
|
+
|
|
106
110
|
async def update_device_props(self, irrigation: Irrigation) -> Irrigation:
|
|
107
111
|
"""Update the irrigation device with latest data from Wyze API."""
|
|
108
112
|
# Get IoT properties
|
|
109
|
-
properties = (await self.get_iot_prop(irrigation))[
|
|
110
|
-
|
|
113
|
+
properties = (await self.get_iot_prop(irrigation))["data"]["props"]
|
|
114
|
+
|
|
111
115
|
# Update device properties
|
|
112
|
-
irrigation.RSSI = properties.get(
|
|
113
|
-
irrigation.IP = properties.get(
|
|
114
|
-
irrigation.sn = properties.get(
|
|
115
|
-
irrigation.ssid = properties.get(
|
|
116
|
-
irrigation.available = (
|
|
116
|
+
irrigation.RSSI = properties.get("RSSI")
|
|
117
|
+
irrigation.IP = properties.get("IP")
|
|
118
|
+
irrigation.sn = properties.get("sn")
|
|
119
|
+
irrigation.ssid = properties.get("ssid")
|
|
120
|
+
irrigation.available = (
|
|
121
|
+
properties.get(IrrigationProps.IOT_STATE.value) == "connected"
|
|
122
|
+
)
|
|
117
123
|
|
|
118
124
|
return irrigation
|
|
119
125
|
|
|
@@ -121,18 +127,25 @@ class IrrigationService(BaseService):
|
|
|
121
127
|
if self._devices is None:
|
|
122
128
|
self._devices = await self.get_object_list()
|
|
123
129
|
|
|
124
|
-
irrigations = [
|
|
130
|
+
irrigations = [
|
|
131
|
+
device
|
|
132
|
+
for device in self._devices
|
|
133
|
+
if device.type == DeviceTypes.IRRIGATION
|
|
134
|
+
and "BS_WK1" in device.product_model
|
|
135
|
+
]
|
|
125
136
|
|
|
126
137
|
return [Irrigation(irrigation.raw_dict) for irrigation in irrigations]
|
|
127
138
|
|
|
128
|
-
async def start_zone(
|
|
139
|
+
async def start_zone(
|
|
140
|
+
self, irrigation: Device, zone_number: int, quickrun_duration: int
|
|
141
|
+
) -> Dict[Any, Any]:
|
|
129
142
|
"""Start a zone with the specified duration.
|
|
130
|
-
|
|
143
|
+
|
|
131
144
|
Args:
|
|
132
145
|
irrigation: The irrigation device
|
|
133
146
|
zone_number: The zone number to start
|
|
134
147
|
quickrun_duration: Duration in seconds to run the zone
|
|
135
|
-
|
|
148
|
+
|
|
136
149
|
Returns:
|
|
137
150
|
Dict containing the API response
|
|
138
151
|
"""
|
|
@@ -141,20 +154,22 @@ class IrrigationService(BaseService):
|
|
|
141
154
|
|
|
142
155
|
async def stop_running_schedule(self, device: Device) -> Dict[Any, Any]:
|
|
143
156
|
"""Stop any currently running irrigation schedule.
|
|
144
|
-
|
|
157
|
+
|
|
145
158
|
Args:
|
|
146
159
|
device: The irrigation device
|
|
147
|
-
|
|
160
|
+
|
|
148
161
|
Returns:
|
|
149
162
|
Dict containing the API response
|
|
150
163
|
"""
|
|
151
164
|
url = "https://wyze-lockwood-service.wyzecam.com/plugin/irrigation/runningschedule"
|
|
152
|
-
action = "STOP"
|
|
165
|
+
action = "STOP"
|
|
153
166
|
return await self._stop_running_schedule(url, device, action)
|
|
154
167
|
|
|
155
|
-
async def set_zone_quickrun_duration(
|
|
168
|
+
async def set_zone_quickrun_duration(
|
|
169
|
+
self, irrigation: Irrigation, zone_number: int, duration: int
|
|
170
|
+
) -> Irrigation:
|
|
156
171
|
"""Set the quickrun duration for a specific zone.
|
|
157
|
-
|
|
172
|
+
|
|
158
173
|
Args:
|
|
159
174
|
irrigation: The irrigation device
|
|
160
175
|
zone_number: The zone number to configure
|
|
@@ -164,26 +179,68 @@ class IrrigationService(BaseService):
|
|
|
164
179
|
if zone.zone_number == zone_number:
|
|
165
180
|
zone.quickrun_duration = duration
|
|
166
181
|
break
|
|
167
|
-
|
|
182
|
+
|
|
168
183
|
return irrigation
|
|
169
184
|
|
|
170
185
|
# Private implementation methods
|
|
171
186
|
async def get_iot_prop(self, device: Device) -> Dict[Any, Any]:
|
|
172
187
|
"""Get IoT properties for a device."""
|
|
173
188
|
url = "https://wyze-lockwood-service.wyzecam.com/plugin/irrigation/get_iot_prop"
|
|
174
|
-
keys =
|
|
175
|
-
|
|
189
|
+
keys = (
|
|
190
|
+
"zone_state,iot_state,iot_state_update_time,app_version,RSSI,"
|
|
191
|
+
"wifi_mac,sn,device_model,ssid,IP"
|
|
192
|
+
)
|
|
176
193
|
return await self._get_iot_prop(url, device, keys)
|
|
177
194
|
|
|
178
195
|
async def get_device_info(self, device: Device) -> Dict[Any, Any]:
|
|
179
196
|
"""Get device info from Wyze API."""
|
|
180
197
|
url = "https://wyze-lockwood-service.wyzecam.com/plugin/irrigation/device_info"
|
|
181
|
-
keys =
|
|
182
|
-
|
|
183
|
-
|
|
198
|
+
keys = (
|
|
199
|
+
"wiring,sensor,enable_schedules,notification_enable,notification_watering_begins,"
|
|
200
|
+
"notification_watering_ends,notification_watering_is_skipped,skip_low_temp,skip_wind,"
|
|
201
|
+
"skip_rain,skip_saturation"
|
|
202
|
+
)
|
|
184
203
|
return await self._irrigation_device_info(url, device, keys)
|
|
185
204
|
|
|
186
205
|
async def get_zone_by_device(self, device: Device) -> List[Dict[Any, Any]]:
|
|
187
206
|
"""Get zones for a device."""
|
|
188
207
|
url = "https://wyze-lockwood-service.wyzecam.com/plugin/irrigation/zone"
|
|
189
208
|
return await self._get_zone_by_device(url, device)
|
|
209
|
+
|
|
210
|
+
async def get_schedule_runs(self, device: Device) -> Dict[Any, Any]:
|
|
211
|
+
"""Get schedule runs for an irrigation device.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
device: The irrigation device
|
|
215
|
+
|
|
216
|
+
Returns:
|
|
217
|
+
Dict containing running status and zone information if running
|
|
218
|
+
"""
|
|
219
|
+
url = (
|
|
220
|
+
"https://wyze-lockwood-service.wyzecam.com/plugin/irrigation/schedule_runs"
|
|
221
|
+
)
|
|
222
|
+
response = await self._get_schedule_runs(url, device, limit=2)
|
|
223
|
+
|
|
224
|
+
# Process the response and return simplified payload
|
|
225
|
+
result = {"running": False}
|
|
226
|
+
|
|
227
|
+
if "data" in response and "schedules" in response["data"]:
|
|
228
|
+
schedules = response["data"]["schedules"]
|
|
229
|
+
for schedule in schedules:
|
|
230
|
+
schedule_state = schedule.get("schedule_state")
|
|
231
|
+
|
|
232
|
+
if schedule_state == "running":
|
|
233
|
+
result["running"] = True
|
|
234
|
+
# Get zone information from zone_runs
|
|
235
|
+
zone_runs = schedule.get("zone_runs")
|
|
236
|
+
# Use the first zone run for zone info
|
|
237
|
+
zone_run = zone_runs[0]
|
|
238
|
+
result["zone_number"] = zone_run.get("zone_number")
|
|
239
|
+
result["zone_name"] = zone_run.get("zone_name")
|
|
240
|
+
break # Found a running schedule, no need to check others
|
|
241
|
+
else:
|
|
242
|
+
_LOGGER.warning(
|
|
243
|
+
"No schedule data found in response for device %s", device.mac
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
return result
|