Skip to content

Commit

Permalink
Add support for confirmation lamp is on/off
Browse files Browse the repository at this point in the history
before returning.
  • Loading branch information
ehendrix23 committed Feb 11, 2021
1 parent 77832b7 commit b59c60c
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 39 deletions.
49 changes: 35 additions & 14 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@

EMAIL = "<EMAIL>"
PASSWORD = "<PASSWORD>"
ISSUE_COMMANDS = True
ISSUE_COMMANDS = False


def print_info(number: int, device):
print(f" Device {number + 1}: {device.name}")
Expand Down Expand Up @@ -63,35 +64,55 @@ async def main() -> None:
try:
if device.open_allowed:
if device.state == STATE_OPEN:
print(f"Garage door {device.name} is already open")
print(
f"Garage door {device.name} is already open"
)
else:
print(f"Opening garage door {device.name}")
try:
if await device.open(wait_for_state=True):
print(f"Garage door {device.name} has been opened.")
print(
f"Garage door {device.name} has been opened."
)
else:
print(f"Failed to open garage door {device.name}.")
print(
f"Failed to open garage door {device.name}."
)
except MyQError as err:
_LOGGER.error(f"Error when trying to open {device.name}: {str(err)}")
_LOGGER.error(
f"Error when trying to open {device.name}: {str(err)}"
)
else:
print(f"Opening of garage door {device.name} is not allowed.")
print(
f"Opening of garage door {device.name} is not allowed."
)

if device.close_allowed:
if device.state == STATE_CLOSED:
print(f"Garage door {device.name} is already closed")
print(
f"Garage door {device.name} is already closed"
)
else:
print(f"Closing garage door {device.name}")
try:
wait_task = await device.close(wait_for_state=False)
wait_task = await device.close(
wait_for_state=False
)
except MyQError as err:
_LOGGER.error(f"Error when trying to close {device.name}: {str(err)}")
_LOGGER.error(
f"Error when trying to close {device.name}: {str(err)}"
)

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

if await wait_task:
print(f"Garage door {device.name} has been closed.")
print(
f"Garage door {device.name} has been closed."
)
else:
print(f"Failed to close garage door {device.name}.")
print(
f"Failed to close garage door {device.name}."
)

except RequestError as err:
_LOGGER.error(err)
Expand All @@ -110,10 +131,10 @@ async def main() -> None:
if ISSUE_COMMANDS:
try:
print(f"Turning lamp {device.name} on")
await device.turnon()
await asyncio.sleep(15)
await device.turnon(wait_for_state=True)
await asyncio.sleep(5)
print(f"Turning lamp {device.name} off")
await device.turnoff()
await device.turnoff(wait_for_state=True)
except RequestError as err:
_LOGGER.error(err)
print(" ------------------------------")
Expand Down
2 changes: 1 addition & 1 deletion pymyq/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""Define a version constant."""
__version__ = '3.0.2'
__version__ = '3.0.3'
20 changes: 15 additions & 5 deletions pymyq/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
class MyQDevice:
"""Define a generic device."""

def __init__(self, api: "API", device_json: dict, account: str, state_update: datetime) -> None:
def __init__(
self, api: "API", device_json: dict, account: str, state_update: datetime
) -> None:
"""Initialize.
:type account: str
"""
Expand Down Expand Up @@ -118,12 +120,20 @@ async def update(self) -> None:
"""Get the latest info for this device."""
await self._api.update_device_info()

async def wait_for_state(self, current_state: List, new_state: List, last_state_update: datetime) -> bool:
async def wait_for_state(
self,
current_state: List,
new_state: List,
last_state_update: datetime,
timeout: int = WAIT_TIMEOUT,
) -> bool:
# First wait until door state is actually updated.
_LOGGER.debug(f"Waiting until device state has been updated for {self.name}")
wait_timeout = WAIT_TIMEOUT
wait_timeout = timeout
while (
last_state_update == self.device_json["state"].get("last_update", datetime.utcnow()) and wait_timeout > 0
last_state_update
== self.device_json["state"].get("last_update", datetime.utcnow())
and wait_timeout > 0
):
wait_timeout = wait_timeout - 5
await asyncio.sleep(5)
Expand All @@ -135,7 +145,7 @@ async def wait_for_state(self, current_state: List, new_state: List, last_state_

# Wait until the state is to what we want it to be
_LOGGER.debug(f"Waiting until device state for {self.name} is {new_state}")
wait_timeout = WAIT_TIMEOUT
wait_timeout = timeout
while self.state in current_state and wait_timeout > 0:
wait_timeout = wait_timeout - 5
await asyncio.sleep(5)
Expand Down
2 changes: 2 additions & 0 deletions pymyq/garagedoor.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ async def close(self, wait_for_state: bool = False) -> Union[asyncio.Task, bool]
current_state=[STATE_CLOSING],
new_state=[STATE_CLOSED],
last_state_update=self.device_json["state"].get("last_update"),
timeout=60,
), name="MyQ_WaitForClose",
)
if not wait_for_state:
Expand Down Expand Up @@ -105,6 +106,7 @@ async def open(self, wait_for_state: bool = False) -> Union[asyncio.Task, bool]:
current_state=[STATE_OPENING],
new_state=[STATE_OPEN],
last_state_update=self.device_json["state"].get("last_update"),
timeout=60,
), name="MyQ_WaitForOpen",
)

Expand Down
64 changes: 45 additions & 19 deletions pymyq/lamp.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Define MyQ devices."""
import asyncio
import logging
from datetime import datetime
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING, Optional, Union

from .device import MyQDevice

Expand All @@ -10,8 +11,7 @@

_LOGGER = logging.getLogger(__name__)

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

def __init__(self, api: "API", device_json: dict, account: str, state_update: datetime) -> None:
def __init__(
self, api: "API", device_json: dict, account: str, state_update: datetime
) -> None:
"""Initialize.
:type account: str
"""
super().__init__(api=api, account=account, device_json=device_json, state_update=state_update)
super().__init__(
api=api, account=account, device_json=device_json, state_update=state_update
)

@property
def device_state(self) -> Optional[str]:
Expand All @@ -36,14 +40,9 @@ def device_state(self) -> Optional[str]:
else None
)

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

# Set the current state to "closing" right away (in case the user doesn't
# run update() before checking):
self.state = STATE_OFF
await self._send_state_command(
url=COMMAND_URI.format(
account_id=self.account,
Expand All @@ -52,15 +51,26 @@ async def turnoff(self) -> None:
),
command=COMMAND_OFF,
)
self.state = STATE_OFF

async def turnon(self) -> None:
"""Open the device."""
if self.state == STATE_ON:
return
wait_for_state_task = asyncio.create_task(
self.wait_for_state(
current_state=[STATE_ON],
new_state=[STATE_OFF],
last_state_update=self.device_json["state"].get("last_update"),
timeout=30,
),
name="MyQ_WaitForOff",
)
if not wait_for_state:
return wait_for_state_task

_LOGGER.debug("Waiting till light is off")
return await wait_for_state_task

async def turnon(self, wait_for_state: bool = False) -> Union[asyncio.Task, bool]:
"""Turn light on."""

# Set the current state to "opening" right away (in case the user doesn't
# run update() before checking):
self.state = STATE_ON
await self._send_state_command(
url=COMMAND_URI.format(
account_id=self.account,
Expand All @@ -69,3 +79,19 @@ async def turnon(self) -> None:
),
command=COMMAND_ON,
)
self.state = STATE_ON

wait_for_state_task = asyncio.create_task(
self.wait_for_state(
current_state=[STATE_ON],
new_state=[STATE_OFF],
last_state_update=self.device_json["state"].get("last_update"),
timeout=30,
),
name="MyQ_WaitForOn",
)
if not wait_for_state:
return wait_for_state_task

_LOGGER.debug("Waiting till light is on")
return await wait_for_state_task

0 comments on commit b59c60c

Please sign in to comment.