Skip to content

Commit b59c60c

Browse files
committed
Add support for confirmation lamp is on/off
before returning.
1 parent 77832b7 commit b59c60c

File tree

5 files changed

+98
-39
lines changed

5 files changed

+98
-39
lines changed

example.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212

1313
EMAIL = "<EMAIL>"
1414
PASSWORD = "<PASSWORD>"
15-
ISSUE_COMMANDS = True
15+
ISSUE_COMMANDS = False
16+
1617

1718
def print_info(number: int, device):
1819
print(f" Device {number + 1}: {device.name}")
@@ -63,35 +64,55 @@ async def main() -> None:
6364
try:
6465
if device.open_allowed:
6566
if device.state == STATE_OPEN:
66-
print(f"Garage door {device.name} is already open")
67+
print(
68+
f"Garage door {device.name} is already open"
69+
)
6770
else:
6871
print(f"Opening garage door {device.name}")
6972
try:
7073
if await device.open(wait_for_state=True):
71-
print(f"Garage door {device.name} has been opened.")
74+
print(
75+
f"Garage door {device.name} has been opened."
76+
)
7277
else:
73-
print(f"Failed to open garage door {device.name}.")
78+
print(
79+
f"Failed to open garage door {device.name}."
80+
)
7481
except MyQError as err:
75-
_LOGGER.error(f"Error when trying to open {device.name}: {str(err)}")
82+
_LOGGER.error(
83+
f"Error when trying to open {device.name}: {str(err)}"
84+
)
7685
else:
77-
print(f"Opening of garage door {device.name} is not allowed.")
86+
print(
87+
f"Opening of garage door {device.name} is not allowed."
88+
)
7889

7990
if device.close_allowed:
8091
if device.state == STATE_CLOSED:
81-
print(f"Garage door {device.name} is already closed")
92+
print(
93+
f"Garage door {device.name} is already closed"
94+
)
8295
else:
8396
print(f"Closing garage door {device.name}")
8497
try:
85-
wait_task = await device.close(wait_for_state=False)
98+
wait_task = await device.close(
99+
wait_for_state=False
100+
)
86101
except MyQError as err:
87-
_LOGGER.error(f"Error when trying to close {device.name}: {str(err)}")
102+
_LOGGER.error(
103+
f"Error when trying to close {device.name}: {str(err)}"
104+
)
88105

89106
print(f"Device {device.name} is {device.state}")
90107

91108
if await wait_task:
92-
print(f"Garage door {device.name} has been closed.")
109+
print(
110+
f"Garage door {device.name} has been closed."
111+
)
93112
else:
94-
print(f"Failed to close garage door {device.name}.")
113+
print(
114+
f"Failed to close garage door {device.name}."
115+
)
95116

96117
except RequestError as err:
97118
_LOGGER.error(err)
@@ -110,10 +131,10 @@ async def main() -> None:
110131
if ISSUE_COMMANDS:
111132
try:
112133
print(f"Turning lamp {device.name} on")
113-
await device.turnon()
114-
await asyncio.sleep(15)
134+
await device.turnon(wait_for_state=True)
135+
await asyncio.sleep(5)
115136
print(f"Turning lamp {device.name} off")
116-
await device.turnoff()
137+
await device.turnoff(wait_for_state=True)
117138
except RequestError as err:
118139
_LOGGER.error(err)
119140
print(" ------------------------------")

pymyq/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
"""Define a version constant."""
2-
__version__ = '3.0.2'
2+
__version__ = '3.0.3'

pymyq/device.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
class MyQDevice:
1717
"""Define a generic device."""
1818

19-
def __init__(self, api: "API", device_json: dict, account: str, state_update: datetime) -> None:
19+
def __init__(
20+
self, api: "API", device_json: dict, account: str, state_update: datetime
21+
) -> None:
2022
"""Initialize.
2123
:type account: str
2224
"""
@@ -118,12 +120,20 @@ async def update(self) -> None:
118120
"""Get the latest info for this device."""
119121
await self._api.update_device_info()
120122

121-
async def wait_for_state(self, current_state: List, new_state: List, last_state_update: datetime) -> bool:
123+
async def wait_for_state(
124+
self,
125+
current_state: List,
126+
new_state: List,
127+
last_state_update: datetime,
128+
timeout: int = WAIT_TIMEOUT,
129+
) -> bool:
122130
# First wait until door state is actually updated.
123131
_LOGGER.debug(f"Waiting until device state has been updated for {self.name}")
124-
wait_timeout = WAIT_TIMEOUT
132+
wait_timeout = timeout
125133
while (
126-
last_state_update == self.device_json["state"].get("last_update", datetime.utcnow()) and wait_timeout > 0
134+
last_state_update
135+
== self.device_json["state"].get("last_update", datetime.utcnow())
136+
and wait_timeout > 0
127137
):
128138
wait_timeout = wait_timeout - 5
129139
await asyncio.sleep(5)
@@ -135,7 +145,7 @@ async def wait_for_state(self, current_state: List, new_state: List, last_state_
135145

136146
# Wait until the state is to what we want it to be
137147
_LOGGER.debug(f"Waiting until device state for {self.name} is {new_state}")
138-
wait_timeout = WAIT_TIMEOUT
148+
wait_timeout = timeout
139149
while self.state in current_state and wait_timeout > 0:
140150
wait_timeout = wait_timeout - 5
141151
await asyncio.sleep(5)

pymyq/garagedoor.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ async def close(self, wait_for_state: bool = False) -> Union[asyncio.Task, bool]
7878
current_state=[STATE_CLOSING],
7979
new_state=[STATE_CLOSED],
8080
last_state_update=self.device_json["state"].get("last_update"),
81+
timeout=60,
8182
), name="MyQ_WaitForClose",
8283
)
8384
if not wait_for_state:
@@ -105,6 +106,7 @@ async def open(self, wait_for_state: bool = False) -> Union[asyncio.Task, bool]:
105106
current_state=[STATE_OPENING],
106107
new_state=[STATE_OPEN],
107108
last_state_update=self.device_json["state"].get("last_update"),
109+
timeout=60,
108110
), name="MyQ_WaitForOpen",
109111
)
110112

pymyq/lamp.py

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Define MyQ devices."""
2+
import asyncio
23
import logging
34
from datetime import datetime
4-
from typing import TYPE_CHECKING, Optional
5+
from typing import TYPE_CHECKING, Optional, Union
56

67
from .device import MyQDevice
78

@@ -10,8 +11,7 @@
1011

1112
_LOGGER = logging.getLogger(__name__)
1213

13-
COMMAND_URI = \
14-
"https://account-devices-lamp.myq-cloud.com/api/v5.2/Accounts/{account_id}/lamps/{device_serial}/{command}"
14+
COMMAND_URI = "https://account-devices-lamp.myq-cloud.com/api/v5.2/Accounts/{account_id}/lamps/{device_serial}/{command}"
1515
COMMAND_ON = "on"
1616
COMMAND_OFF = "off"
1717
STATE_ON = "on"
@@ -21,11 +21,15 @@
2121
class MyQLamp(MyQDevice):
2222
"""Define a generic device."""
2323

24-
def __init__(self, api: "API", device_json: dict, account: str, state_update: datetime) -> None:
24+
def __init__(
25+
self, api: "API", device_json: dict, account: str, state_update: datetime
26+
) -> None:
2527
"""Initialize.
2628
:type account: str
2729
"""
28-
super().__init__(api=api, account=account, device_json=device_json, state_update=state_update)
30+
super().__init__(
31+
api=api, account=account, device_json=device_json, state_update=state_update
32+
)
2933

3034
@property
3135
def device_state(self) -> Optional[str]:
@@ -36,14 +40,9 @@ def device_state(self) -> Optional[str]:
3640
else None
3741
)
3842

39-
async def turnoff(self) -> None:
40-
"""Close the device."""
41-
if self.state == STATE_OFF:
42-
return
43+
async def turnoff(self, wait_for_state: bool = False) -> Union[asyncio.Task, bool]:
44+
"""Turn light off."""
4345

44-
# Set the current state to "closing" right away (in case the user doesn't
45-
# run update() before checking):
46-
self.state = STATE_OFF
4746
await self._send_state_command(
4847
url=COMMAND_URI.format(
4948
account_id=self.account,
@@ -52,15 +51,26 @@ async def turnoff(self) -> None:
5251
),
5352
command=COMMAND_OFF,
5453
)
54+
self.state = STATE_OFF
5555

56-
async def turnon(self) -> None:
57-
"""Open the device."""
58-
if self.state == STATE_ON:
59-
return
56+
wait_for_state_task = asyncio.create_task(
57+
self.wait_for_state(
58+
current_state=[STATE_ON],
59+
new_state=[STATE_OFF],
60+
last_state_update=self.device_json["state"].get("last_update"),
61+
timeout=30,
62+
),
63+
name="MyQ_WaitForOff",
64+
)
65+
if not wait_for_state:
66+
return wait_for_state_task
67+
68+
_LOGGER.debug("Waiting till light is off")
69+
return await wait_for_state_task
70+
71+
async def turnon(self, wait_for_state: bool = False) -> Union[asyncio.Task, bool]:
72+
"""Turn light on."""
6073

61-
# Set the current state to "opening" right away (in case the user doesn't
62-
# run update() before checking):
63-
self.state = STATE_ON
6474
await self._send_state_command(
6575
url=COMMAND_URI.format(
6676
account_id=self.account,
@@ -69,3 +79,19 @@ async def turnon(self) -> None:
6979
),
7080
command=COMMAND_ON,
7181
)
82+
self.state = STATE_ON
83+
84+
wait_for_state_task = asyncio.create_task(
85+
self.wait_for_state(
86+
current_state=[STATE_ON],
87+
new_state=[STATE_OFF],
88+
last_state_update=self.device_json["state"].get("last_update"),
89+
timeout=30,
90+
),
91+
name="MyQ_WaitForOn",
92+
)
93+
if not wait_for_state:
94+
return wait_for_state_task
95+
96+
_LOGGER.debug("Waiting till light is on")
97+
return await wait_for_state_task

0 commit comments

Comments
 (0)