348 lines
12 KiB
Python
Raw Normal View History

2022-04-01 15:02:13 +02:00
"""Classes for VeSync Switch Devices."""
from abc import ABCMeta, abstractmethod
import json
import logging
from typing import Dict, Union
from .helpers import Helpers as helpers
from .vesyncbasedevice import VeSyncBaseDevice
logger = logging.getLogger(__name__)
feature_dict: Dict[str, Dict[str, Union[list, str]]] = {
"ESWL01": {"module": "VeSyncWallSwitch", "features": []},
"ESWD16": {"module": "VeSyncDimmerSwitch", "features": ["dimmable"]},
"ESWL03": {"module": "VeSyncWallSwitch", "features": []},
}
switch_modules: dict = {k: v["module"] for k, v in feature_dict.items()}
__all__: list = list(switch_modules.values()) + ["switch_modules"]
class VeSyncSwitch(VeSyncBaseDevice):
"""Etekcity Switch Base Class."""
__metaclasss__ = ABCMeta
def __init__(self, details, manager):
"""Initialize Switch Base Class."""
super().__init__(details, manager)
self.features = feature_dict.get(self.device_type, {}).get("features")
if self.features is None:
logger.error("No configuration set for - %s", self.device_name)
raise RuntimeError(f"No configuration set for - {self.device_name}")
self.details = {}
def is_dimmable(self) -> bool:
"""Return True if switch is dimmable."""
return bool("dimmable" in self.features)
@abstractmethod
def get_details(self) -> None:
"""Get Device Details."""
@abstractmethod
def turn_on(self) -> bool:
"""Turn Switch On."""
@abstractmethod
def turn_off(self) -> bool:
"""Turn switch off."""
@abstractmethod
def get_config(self) -> None:
"""Get configuration and firmware deatils."""
@property
def active_time(self) -> int:
"""Get active time of switch."""
return self.details.get("active_time", 0)
def update(self) -> None:
"""Update device details."""
self.get_details()
class VeSyncWallSwitch(VeSyncSwitch):
"""Etekcity standard wall switch class."""
def __init__(self, details, manager):
"""Initialize standard etekcity wall switch class."""
super().__init__(details, manager)
def get_details(self) -> None:
"""Get switch device details."""
body = helpers.req_body(self.manager, "devicedetail")
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
r, _ = helpers.call_api(
"/inwallswitch/v1/device/devicedetail", "post", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self.device_status = r.get("deviceStatus", self.device_status)
self.details["active_time"] = r.get("activeTime", 0)
self.connection_status = r.get("connectionStatus", self.connection_status)
else:
logger.debug("Error getting %s details", self.device_name)
def get_config(self) -> None:
"""Get switch device configuration info."""
body = helpers.req_body(self.manager, "devicedetail")
body["method"] = "configurations"
body["uuid"] = self.uuid
r, _ = helpers.call_api(
"/inwallswitch/v1/device/configurations",
"post",
headers=helpers.req_headers(self.manager),
json=body,
)
if helpers.code_check(r):
self.config = helpers.build_config_dict(r)
else:
logger.warning("Unable to get %s config info", self.device_name)
def turn_off(self) -> bool:
"""Turn off switch device."""
body = helpers.req_body(self.manager, "devicestatus")
body["status"] = "off"
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
r, _ = helpers.call_api(
"/inwallswitch/v1/device/devicestatus", "put", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self.device_status = "off"
return True
logger.warning("Error turning %s off", self.device_name)
return False
def turn_on(self) -> bool:
"""Turn on switch device."""
body = helpers.req_body(self.manager, "devicestatus")
body["status"] = "on"
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
r, _ = helpers.call_api(
"/inwallswitch/v1/device/devicestatus", "put", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self.device_status = "on"
return True
logger.warning("Error turning %s on", self.device_name)
return False
class VeSyncDimmerSwitch(VeSyncSwitch):
"""Vesync Dimmer Switch Class with RGB Faceplate."""
def __init__(self, details, manager):
"""Initialize dimmer switch class."""
super().__init__(details, manager)
self._brightness = 0
self._rgb_value = {"red": 0, "blue": 0, "green": 0}
self._rgb_status = "unknown"
self._indicator_light = "unknown"
def get_details(self) -> None:
"""Get dimmer switch details."""
body = helpers.req_body(self.manager, "devicedetail")
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
r, _ = helpers.call_api(
"/dimmer/v1/device/devicedetail", "post", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self.device_status = r.get("deviceStatus", self.device_status)
self.details["active_time"] = r.get("activeTime", 0)
self.connection_status = r.get("connectionStatus", self.connection_status)
self._brightness = r.get("brightness")
self._rgb_status = r.get("rgbStatus")
self._rgb_value = r.get("rgbValue")
self._indicator_light = r.get("indicatorlightStatus")
else:
logger.debug("Error getting %s details", self.device_name)
@property
def brightness(self) -> float:
"""Return brightness in percent."""
return self._brightness
@property
def indicator_light_status(self) -> str:
"""Faceplate brightness light status."""
return self._indicator_light
@property
def rgb_light_status(self) -> str:
"""RGB Faceplate light status."""
return self._rgb_status
@property
def rgb_light_value(self) -> dict:
"""RGB Light Values."""
return self._rgb_value
def switch_toggle(self, status: str) -> bool:
"""Toggle switch status."""
if status not in ["on", "off"]:
logger.debug("Invalid status passed to wall switch")
return False
body = helpers.req_body(self.manager, "devicestatus")
body["status"] = status
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
r, _ = helpers.call_api(
"/dimmer/v1/device/devicestatus", "put", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self.device_status = status
return True
logger.warning("Error turning %s %s", self.device_name, status)
return False
def turn_on(self) -> bool:
"""Turn switch on."""
return self.switch_toggle("on")
def turn_off(self) -> bool:
"""Turn switch off."""
return self.switch_toggle("off")
def indicator_light_toggle(self, status: str) -> bool:
"""Toggle indicator light."""
if status not in ["on", "off"]:
logger.debug("Invalid status for wall switch")
return False
body = helpers.req_body(self.manager, "devicestatus")
body["status"] = status
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
r, _ = helpers.call_api(
"/dimmer/v1/device/indicatorlightstatus", "put", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self.device_status = status
return True
logger.warning("Error turning %s indicator light %s", self.device_name, status)
return False
def indicator_light_on(self) -> bool:
"""Turn Indicator light on."""
return self.indicator_light_toggle("on")
def indicator_light_off(self) -> bool:
"""Turn indicator light off."""
return self.indicator_light_toggle("off")
def rgb_color_status(
self, status: str, red: int = None, blue: int = None, green: int = None
) -> bool:
"""Set faceplate RGB color."""
body = helpers.req_body(self.manager, "devicestatus")
body["status"] = status
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
if red is not None and blue is not None and green is not None:
body["rgbValue"] = {"red": red, "blue": blue, "green": green}
r, _ = helpers.call_api(
"/dimmer/v1/device/devicergbstatus", "put", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self._rgb_status = status
if body.get("rgbValue") is not None:
self._rgb_value = {"red": red, "blue": blue, "green": green}
return True
logger.warning("Error turning %s off", self.device_name)
return False
def rgb_color_off(self) -> bool:
"""Turn RGB Color Off."""
return self.rgb_color_status("off")
def rgb_color_on(self) -> bool:
"""Turn RGB Color Off."""
return self.rgb_color_status("on")
def rgb_color_set(self, red: int, green: int, blue: int) -> bool:
"""Set RGB color of faceplate."""
if isinstance(red, int) and isinstance(green, int) and isinstance(blue, int):
for color in [red, green, blue]:
if color < 0 or color > 255:
logger.warning("Invalid RGB value")
return False
return bool(self.rgb_color_status("on", red, green, blue))
return False
def set_brightness(self, brightness: int) -> bool:
"""Set brightness of dimmer - 1 - 100."""
if isinstance(brightness, int) and (brightness > 0 or brightness <= 100):
body = helpers.req_body(self.manager, "devicestatus")
body["brightness"] = brightness
body["uuid"] = self.uuid
head = helpers.req_headers(self.manager)
r, _ = helpers.call_api(
"/dimmer/v1/device/updatebrightness", "put", headers=head, json=body
)
if r is not None and helpers.code_check(r):
self._brightness = brightness
return True
logger.warning("Error setting %s brightness", self.device_name)
else:
logger.warning("Invalid brightness")
return False
def displayJSON(self) -> str:
"""JSON API for dimmer switch."""
sup_val = json.loads(super().displayJSON())
if self.is_dimmable:
sup_val.update(
{
"Indicator Light": str(self.active_time),
"Brightness": str(self._brightness),
"RGB Light": str(self._rgb_status),
}
)
return sup_val
def get_config(self) -> None:
"""Get dimmable switch device configuration info."""
body = helpers.req_body(self.manager, "devicedetail")
body["method"] = "configurations"
body["uuid"] = self.uuid
r, _ = helpers.call_api(
"/dimmer/v1/device/configurations",
"post",
headers=helpers.req_headers(self.manager),
json=body,
)
if helpers.code_check(r):
self.config = helpers.build_config_dict(r)
else:
logger.warning("Unable to get %s config info", self.device_name)