mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-01-24 05:37:59 +00:00
make SmartStrip use asyncio
This commit is contained in:
parent
b6a0542f43
commit
ba2600cb93
@ -1,9 +1,11 @@
|
|||||||
|
import asyncio
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional, Union
|
from typing import Any, Dict, Optional, Union
|
||||||
from deprecation import deprecated
|
|
||||||
|
|
||||||
from pyHS100 import SmartPlug, SmartDeviceException, EmeterStatus, DeviceType
|
from deprecation import deprecated
|
||||||
|
from pyHS100 import DeviceType, EmeterStatus, SmartDeviceException, SmartPlug
|
||||||
|
|
||||||
from .protocol import TPLinkSmartHomeProtocol
|
from .protocol import TPLinkSmartHomeProtocol
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -42,7 +44,9 @@ class SmartStrip(SmartPlug):
|
|||||||
self.emeter_type = "emeter"
|
self.emeter_type = "emeter"
|
||||||
self._device_type = DeviceType.Strip
|
self._device_type = DeviceType.Strip
|
||||||
self.plugs = {}
|
self.plugs = {}
|
||||||
children = self.sys_info["children"]
|
|
||||||
|
sys_info = asyncio.run(self.get_sys_info())
|
||||||
|
children = sys_info["children"]
|
||||||
self.num_children = len(children)
|
self.num_children = len(children)
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
self.plugs[plug] = SmartPlug(
|
self.plugs[plug] = SmartPlug(
|
||||||
@ -59,14 +63,7 @@ class SmartStrip(SmartPlug):
|
|||||||
if index not in range(self.num_children):
|
if index not in range(self.num_children):
|
||||||
raise SmartStripException("plug index of %d " "is out of bounds" % index)
|
raise SmartStripException("plug index of %d " "is out of bounds" % index)
|
||||||
|
|
||||||
@property
|
async def get_state(self, *, index=-1) -> Dict[int, str]:
|
||||||
@deprecated(details="use is_on, get_is_on()")
|
|
||||||
def state(self) -> bool:
|
|
||||||
if self.is_on:
|
|
||||||
return self.STATE_ON
|
|
||||||
return self.STATE_OFF
|
|
||||||
|
|
||||||
def get_state(self, *, index=-1) -> Dict[int, str]:
|
|
||||||
"""Retrieve the switch state
|
"""Retrieve the switch state
|
||||||
|
|
||||||
:returns: list with the state of each child plug
|
:returns: list with the state of each child plug
|
||||||
@ -75,36 +72,14 @@ class SmartStrip(SmartPlug):
|
|||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _state_for_bool(b):
|
def _state_for_bool(_bool):
|
||||||
return SmartPlug.STATE_ON if b else SmartPlug.STATE_OFF
|
return SmartPlug.STATE_ON if _bool else SmartPlug.STATE_OFF
|
||||||
|
|
||||||
is_on = self.get_is_on(index=index)
|
is_on = await self.get_is_on(index=index)
|
||||||
if isinstance(is_on, bool):
|
if isinstance(is_on, bool):
|
||||||
return _state_for_bool(is_on)
|
return _state_for_bool(is_on)
|
||||||
|
|
||||||
print(is_on)
|
return {k: _state_for_bool(v) for k, v in is_on.items()}
|
||||||
|
|
||||||
return {k: _state_for_bool(v) for k, v in self.get_is_on().items()}
|
|
||||||
|
|
||||||
@state.setter
|
|
||||||
@deprecated(details="use turn_on(), turn_off()")
|
|
||||||
def state(self, value: str):
|
|
||||||
"""Sets the state of all plugs in the strip
|
|
||||||
|
|
||||||
:param value: one of
|
|
||||||
STATE_ON
|
|
||||||
STATE_OFF
|
|
||||||
:raises ValueError: on invalid state
|
|
||||||
:raises SmartDeviceException: on error
|
|
||||||
"""
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError("State must be str, not of %s.", type(value))
|
|
||||||
elif value.upper() == SmartPlug.STATE_ON:
|
|
||||||
self.turn_on()
|
|
||||||
elif value.upper() == SmartPlug.STATE_OFF:
|
|
||||||
self.turn_off()
|
|
||||||
else:
|
|
||||||
raise ValueError("State %s is not valid.", value)
|
|
||||||
|
|
||||||
def set_state(self, value: str, *, index: int = -1):
|
def set_state(self, value: str, *, index: int = -1):
|
||||||
"""Sets the state of a plug on the strip
|
"""Sets the state of a plug on the strip
|
||||||
@ -123,12 +98,12 @@ class SmartStrip(SmartPlug):
|
|||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
self.plugs[index].state = value
|
self.plugs[index].state = value
|
||||||
|
|
||||||
@property
|
async def is_on(self) -> bool:
|
||||||
def is_on(self) -> bool:
|
|
||||||
"""Return if any of the outlets are on"""
|
"""Return if any of the outlets are on"""
|
||||||
return any(state == "ON" for state in self.get_state().values())
|
states = await self.get_state()
|
||||||
|
return any(state == "ON" for state in states.values())
|
||||||
|
|
||||||
def get_is_on(self, *, index: int = -1) -> Any:
|
async def get_is_on(self, *, index: int = -1) -> Any:
|
||||||
"""
|
"""
|
||||||
Returns whether device is on.
|
Returns whether device is on.
|
||||||
|
|
||||||
@ -138,7 +113,8 @@ class SmartStrip(SmartPlug):
|
|||||||
Dict[int, bool] if no index provided
|
Dict[int, bool] if no index provided
|
||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
children = self.sys_info["children"]
|
sys_info = await self.get_sys_info()
|
||||||
|
children = sys_info["children"]
|
||||||
if index < 0:
|
if index < 0:
|
||||||
is_on = {}
|
is_on = {}
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
@ -148,14 +124,14 @@ class SmartStrip(SmartPlug):
|
|||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
return bool(children[index]["state"])
|
return bool(children[index]["state"])
|
||||||
|
|
||||||
def get_is_off(self, *, index: int = -1) -> Any:
|
async def get_is_off(self, *, index: int = -1) -> Any:
|
||||||
is_on = self.get_is_on(index=index)
|
is_on = await self.get_is_on(index=index)
|
||||||
if isinstance(is_on, bool):
|
if isinstance(is_on, bool):
|
||||||
return not is_on
|
return not is_on
|
||||||
else:
|
else:
|
||||||
return {k: not v for k, v in is_on}
|
return {k: not v for k, v in is_on}
|
||||||
|
|
||||||
def turn_on(self, *, index: int = -1):
|
async def turn_on(self, *, index: int = -1):
|
||||||
"""
|
"""
|
||||||
Turns outlets on
|
Turns outlets on
|
||||||
|
|
||||||
@ -164,12 +140,12 @@ class SmartStrip(SmartPlug):
|
|||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
if index < 0:
|
if index < 0:
|
||||||
self._query_helper("system", "set_relay_state", {"state": 1})
|
await self._query_helper("system", "set_relay_state", {"state": 1})
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
self.plugs[index].turn_on()
|
await self.plugs[index].turn_on()
|
||||||
|
|
||||||
def turn_off(self, *, index: int = -1):
|
async def turn_off(self, *, index: int = -1):
|
||||||
"""
|
"""
|
||||||
Turns outlets off
|
Turns outlets off
|
||||||
|
|
||||||
@ -178,17 +154,17 @@ class SmartStrip(SmartPlug):
|
|||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
if index < 0:
|
if index < 0:
|
||||||
self._query_helper("system", "set_relay_state", {"state": 0})
|
await self._query_helper("system", "set_relay_state", {"state": 0})
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
self.plugs[index].turn_off()
|
await self.plugs[index].turn_off()
|
||||||
|
|
||||||
@property
|
async def get_on_since(self) -> datetime:
|
||||||
def on_since(self) -> datetime:
|
|
||||||
"""Returns the maximum on-time of all outlets."""
|
"""Returns the maximum on-time of all outlets."""
|
||||||
return max(v for v in self.get_on_since().values())
|
on_since = await self._get_on_since()
|
||||||
|
return max(v for v in await on_since.values())
|
||||||
|
|
||||||
def get_on_since(self, *, index: int = -1) -> Any:
|
async def _get_on_since(self, *, index: int = -1) -> Any:
|
||||||
"""
|
"""
|
||||||
Returns pretty-printed on-time
|
Returns pretty-printed on-time
|
||||||
|
|
||||||
@ -200,7 +176,8 @@ class SmartStrip(SmartPlug):
|
|||||||
"""
|
"""
|
||||||
if index < 0:
|
if index < 0:
|
||||||
on_since = {}
|
on_since = {}
|
||||||
children = self.sys_info["children"]
|
sys_info = await self.get_sys_info()
|
||||||
|
children = sys_info["children"]
|
||||||
|
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
child_ontime = children[plug]["on_time"]
|
child_ontime = children[plug]["on_time"]
|
||||||
@ -210,19 +187,18 @@ class SmartStrip(SmartPlug):
|
|||||||
return on_since
|
return on_since
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
return self.plugs[index].on_since
|
return await self.plugs[index].get_on_since()
|
||||||
|
|
||||||
@property
|
async def get_state_information(self) -> Dict[str, Any]:
|
||||||
def state_information(self) -> Dict[str, Any]:
|
|
||||||
"""
|
"""
|
||||||
Returns strip-specific state information.
|
Returns strip-specific state information.
|
||||||
|
|
||||||
:return: Strip information dict, keys in user-presentable form.
|
:return: Strip information dict, keys in user-presentable form.
|
||||||
:rtype: dict
|
:rtype: dict
|
||||||
"""
|
"""
|
||||||
state = {"LED state": self.led}
|
state = {"LED state": await self.get_led()} # XXX: from where?
|
||||||
is_on = self.get_is_on()
|
is_on = await self.get_is_on()
|
||||||
on_since = self.get_on_since()
|
on_since = await self._get_on_since()
|
||||||
for plug_index in range(self.num_children):
|
for plug_index in range(self.num_children):
|
||||||
plug_number = plug_index + 1
|
plug_number = plug_index + 1
|
||||||
if is_on[plug_index]:
|
if is_on[plug_index]:
|
||||||
@ -230,7 +206,7 @@ class SmartStrip(SmartPlug):
|
|||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
||||||
def get_emeter_realtime(self, *, index: int = -1) -> Optional[Any]:
|
async def get_emeter_realtime(self, *, index: int = -1) -> Optional[Any]:
|
||||||
"""
|
"""
|
||||||
Retrieve current energy readings from device
|
Retrieve current energy readings from device
|
||||||
|
|
||||||
@ -243,19 +219,19 @@ class SmartStrip(SmartPlug):
|
|||||||
:raises SmartDeviceException: on error
|
:raises SmartDeviceException: on error
|
||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
if not self.has_emeter: # pragma: no cover
|
if not await self.get_has_emeter(): # pragma: no cover
|
||||||
raise SmartStripException("Device has no emeter")
|
raise SmartStripException("Device has no emeter")
|
||||||
|
|
||||||
if index < 0:
|
if index < 0:
|
||||||
emeter_status = {}
|
emeter_status = {}
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
emeter_status[plug] = self.plugs[plug].get_emeter_realtime()
|
emeter_status[plug] = await self.plugs[plug].get_emeter_realtime()
|
||||||
return emeter_status
|
return emeter_status
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
return self.plugs[index].get_emeter_realtime()
|
return await self.plugs[index].get_emeter_realtime()
|
||||||
|
|
||||||
def current_consumption(self, *, index: int = -1) -> Optional[Any]:
|
async def current_consumption(self, *, index: int = -1) -> Optional[Any]:
|
||||||
"""
|
"""
|
||||||
Get the current power consumption in Watts.
|
Get the current power consumption in Watts.
|
||||||
|
|
||||||
@ -269,19 +245,19 @@ class SmartStrip(SmartPlug):
|
|||||||
:raises SmartDeviceException: on error
|
:raises SmartDeviceException: on error
|
||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
if not self.has_emeter: # pragma: no cover
|
if not await self.get_has_emeter(): # pragma: no cover
|
||||||
raise SmartStripException("Device has no emeter")
|
raise SmartStripException("Device has no emeter")
|
||||||
|
|
||||||
if index < 0:
|
if index < 0:
|
||||||
consumption = {}
|
consumption = {}
|
||||||
emeter_reading = self.get_emeter_realtime()
|
emeter_reading = await self.get_emeter_realtime()
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
response = EmeterStatus(emeter_reading[plug])
|
response = EmeterStatus(emeter_reading[plug])
|
||||||
consumption[plug] = response["power"]
|
consumption[plug] = response["power"]
|
||||||
return consumption
|
return consumption
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
response = EmeterStatus(self.get_emeter_realtime(index=index))
|
response = EmeterStatus(await self.get_emeter_realtime(index=index))
|
||||||
return response["power"]
|
return response["power"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -291,7 +267,7 @@ class SmartStrip(SmartPlug):
|
|||||||
"""
|
"""
|
||||||
return {"icon": "SMARTSTRIP-DUMMY", "hash": "SMARTSTRIP-DUMMY"}
|
return {"icon": "SMARTSTRIP-DUMMY", "hash": "SMARTSTRIP-DUMMY"}
|
||||||
|
|
||||||
def get_alias(self, *, index: int = -1) -> Union[str, Dict[int, str]]:
|
async def get_alias(self, *, index: int = -1) -> Union[str, Dict[int, str]]:
|
||||||
"""Gets the alias for a plug.
|
"""Gets the alias for a plug.
|
||||||
|
|
||||||
:param index: plug index (-1 for all)
|
:param index: plug index (-1 for all)
|
||||||
@ -301,7 +277,8 @@ class SmartStrip(SmartPlug):
|
|||||||
Dict[int, str] if no index provided
|
Dict[int, str] if no index provided
|
||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
children = self.sys_info["children"]
|
sys_info = await self.get_sys_info()
|
||||||
|
children = sys_info["children"]
|
||||||
|
|
||||||
if index < 0:
|
if index < 0:
|
||||||
alias = {}
|
alias = {}
|
||||||
@ -312,7 +289,7 @@ class SmartStrip(SmartPlug):
|
|||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
return children[index]["alias"]
|
return children[index]["alias"]
|
||||||
|
|
||||||
def set_alias(self, alias: str, *, index: int = -1):
|
async def set_alias(self, alias: str, *, index: int = -1):
|
||||||
"""Sets the alias for a plug
|
"""Sets the alias for a plug
|
||||||
|
|
||||||
:param index: plug index
|
:param index: plug index
|
||||||
@ -325,9 +302,9 @@ class SmartStrip(SmartPlug):
|
|||||||
return super().set_alias(alias)
|
return super().set_alias(alias)
|
||||||
|
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
self.plugs[index].set_alias(alias)
|
await self.plugs[index].set_alias(alias)
|
||||||
|
|
||||||
def get_emeter_daily(
|
async def get_emeter_daily(
|
||||||
self, year: int = None, month: int = None, kwh: bool = True, *, index: int = -1
|
self, year: int = None, month: int = None, kwh: bool = True, *, index: int = -1
|
||||||
) -> Dict:
|
) -> Dict:
|
||||||
"""Retrieve daily statistics for a given month
|
"""Retrieve daily statistics for a given month
|
||||||
@ -342,21 +319,23 @@ class SmartStrip(SmartPlug):
|
|||||||
:raises SmartDeviceException: on error
|
:raises SmartDeviceException: on error
|
||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
if not self.has_emeter: # pragma: no cover
|
if not await self.get_has_emeter(): # pragma: no cover
|
||||||
raise SmartStripException("Device has no emeter")
|
raise SmartStripException("Device has no emeter")
|
||||||
|
|
||||||
emeter_daily = {}
|
emeter_daily = {}
|
||||||
if index < 0:
|
if index < 0:
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
emeter_daily = self.plugs[plug].get_emeter_daily(
|
emeter_daily = await self.plugs[plug].get_emeter_daily(
|
||||||
year=year, month=month, kwh=kwh
|
year=year, month=month, kwh=kwh
|
||||||
)
|
)
|
||||||
return emeter_daily
|
return emeter_daily
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
return self.plugs[index].get_emeter_daily(year=year, month=month, kwh=kwh)
|
return await self.plugs[index].get_emeter_daily(
|
||||||
|
year=year, month=month, kwh=kwh
|
||||||
|
)
|
||||||
|
|
||||||
def get_emeter_monthly(
|
async def get_emeter_monthly(
|
||||||
self, year: int = None, kwh: bool = True, *, index: int = -1
|
self, year: int = None, kwh: bool = True, *, index: int = -1
|
||||||
) -> Dict:
|
) -> Dict:
|
||||||
"""Retrieve monthly statistics for a given year.
|
"""Retrieve monthly statistics for a given year.
|
||||||
@ -369,19 +348,21 @@ class SmartStrip(SmartPlug):
|
|||||||
:raises SmartDeviceException: on error
|
:raises SmartDeviceException: on error
|
||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
if not self.has_emeter: # pragma: no cover
|
if not await self.get_has_emeter(): # pragma: no cover
|
||||||
raise SmartStripException("Device has no emeter")
|
raise SmartStripException("Device has no emeter")
|
||||||
|
|
||||||
emeter_monthly = {}
|
emeter_monthly = {}
|
||||||
if index < 0:
|
if index < 0:
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
emeter_monthly = self.plugs[plug].get_emeter_monthly(year=year, kwh=kwh)
|
emeter_monthly[plug] = await self.plugs[plug].get_emeter_monthly(
|
||||||
|
year=year, kwh=kwh
|
||||||
|
)
|
||||||
return emeter_monthly
|
return emeter_monthly
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
return self.plugs[index].get_emeter_monthly(year=year, kwh=kwh)
|
return await self.plugs[index].get_emeter_monthly(year=year, kwh=kwh)
|
||||||
|
|
||||||
def erase_emeter_stats(self, *, index: int = -1) -> bool:
|
async def erase_emeter_stats(self, *, index: int = -1) -> bool:
|
||||||
"""Erase energy meter statistics
|
"""Erase energy meter statistics
|
||||||
|
|
||||||
:param index: plug index (-1 for all)
|
:param index: plug index (-1 for all)
|
||||||
@ -391,15 +372,15 @@ class SmartStrip(SmartPlug):
|
|||||||
:raises SmartDeviceException: on error
|
:raises SmartDeviceException: on error
|
||||||
:raises SmartStripException: index out of bounds
|
:raises SmartStripException: index out of bounds
|
||||||
"""
|
"""
|
||||||
if not self.has_emeter: # pragma: no cover
|
if not await self.get_has_emeter(): # pragma: no cover
|
||||||
raise SmartStripException("Device has no emeter")
|
raise SmartStripException("Device has no emeter")
|
||||||
|
|
||||||
if index < 0:
|
if index < 0:
|
||||||
for plug in range(self.num_children):
|
for plug in range(self.num_children):
|
||||||
self.plugs[plug].erase_emeter_stats()
|
await self.plugs[plug].erase_emeter_stats()
|
||||||
else:
|
else:
|
||||||
self.raise_for_index(index)
|
self.raise_for_index(index)
|
||||||
self.plugs[index].erase_emeter_stats()
|
await self.plugs[index].erase_emeter_stats()
|
||||||
|
|
||||||
# As query_helper raises exception in case of failure, we have
|
# As query_helper raises exception in case of failure, we have
|
||||||
# succeeded when we are this far.
|
# succeeded when we are this far.
|
||||||
|
Loading…
Reference in New Issue
Block a user