Example #1
0
    def _get_device_class(info: dict) -> Type[SmartDevice]:
        """Find SmartDevice subclass for device described by passed data."""
        if "system" in info and "get_sysinfo" in info["system"]:
            sysinfo = info["system"]["get_sysinfo"]
            if "type" in sysinfo:
                type_ = sysinfo["type"]
            elif "mic_type" in sysinfo:
                type_ = sysinfo["mic_type"]
            else:
                raise SmartDeviceException(
                    "Unable to find the device type field!")
        else:
            raise SmartDeviceException(
                "No 'system' nor 'get_sysinfo' in response")

        if ("smartlife.iot.dimmer" in info
                and "get_dimmer_parameters" in info["smartlife.iot.dimmer"]):
            return SmartDimmer

        elif "smartplug" in type_.lower() and "children" in sysinfo:
            return SmartStrip

        elif "smartplug" in type_.lower():
            if "children" in sysinfo:
                return SmartStrip

            return SmartPlug
        elif "smartbulb" in type_.lower():
            if "length" in sysinfo:  # strips have length
                return SmartLightStrip

            return SmartBulb

        raise SmartDeviceException("Unknown device type: %s", type_)
Example #2
0
    def valid_temperature_range(self) -> Tuple[int, int]:
        """Return the device-specific white temperature range (in Kelvin).

        :return: White temperature range in Kelvin (minimum, maximum)
        """
        if not self.is_variable_color_temp:
            raise SmartDeviceException("Color temperature not supported")
        for model, temp_range in AZTECH_KELVIN.items():
            sys_info = self.sys_info
            if re.match(model, sys_info["model"]):
                return temp_range

        raise SmartDeviceException(
            "Unknown color temperature range, please open an issue on github"
        )
Example #3
0
    def brightness(self) -> int:
        """Return the current brightness in percentage."""
        if not self.is_dimmable:  # pragma: no cover
            raise SmartDeviceException("Bulb is not dimmable.")

        light_state = self.light_state
        return int(light_state["brightness"])
Example #4
0
    def color_temp(self) -> int:
        """Return color temperature of the device in kelvin."""
        if not self.is_variable_color_temp:
            raise SmartDeviceException("Bulb does not support colortemp.")

        light_state = self.light_state
        return int(light_state["color_temp"])
Example #5
0
    async def set_hsv(
        self, hue: int, saturation: int, value: int, *, transition: int = None
    ) -> Dict:
        """Set new HSV.

        :param int hue: hue in degrees
        :param int saturation: saturation in percentage [0,100]
        :param int value: value in percentage [0, 100]
        :param int transition: transition in milliseconds.
        """
        if not self.is_color:
            raise SmartDeviceException("Bulb does not support color.")

        if not isinstance(hue, int) or not (0 <= hue <= 360):
            raise ValueError(
                "Invalid hue value: {} " "(valid range: 0-360)".format(hue)
            )

        if not isinstance(saturation, int) or not (0 <= saturation <= 100):
            raise ValueError(
                "Invalid saturation value: {} "
                "(valid range: 0-100%)".format(saturation)
            )

        self._raise_for_invalid_brightness(value)

        light_state = {
            "hue": hue,
            "saturation": saturation,
            "brightness": value,
            "color_temp": 0,
        }

        return await self.set_light_state(light_state, transition=transition)
Example #6
0
    def _get_child_info(self) -> Dict:
        """Return the subdevice information for this device."""
        for plug in self.parent.sys_info["children"]:
            if plug["id"] == self.child_id:
                return plug

        raise SmartDeviceException(f"Unable to find children {self.child_id}")
Example #7
0
    async def set_brightness(self, brightness: int, *, transition: int = None):
        """Set the new dimmer brightness level in percentage.

        :param int transition: transition duration in milliseconds.
            Using a transition will cause the dimmer to turn on.
        """
        if not self.is_dimmable:
            raise SmartDeviceException("Device is not dimmable.")

        if not isinstance(brightness, int):
            raise ValueError("Brightness must be integer, "
                             "not of %s.", type(brightness))

        if not 0 <= brightness <= 100:
            raise ValueError("Brightness value %s is not valid." % brightness)

        # Dimmers do not support a brightness of 0, but bulbs do.
        # Coerce 0 to 1 to maintain the same interface between dimmers and bulbs.
        if brightness == 0:
            brightness = 1

        if transition is not None:
            return await self.set_dimmer_transition(brightness, transition)

        return await self._query_helper(self.DIMMER_SERVICE, "set_brightness",
                                        {"brightness": brightness})
Example #8
0
    def brightness(self) -> int:
        """Return current brightness on dimmers.

        Will return a range between 0 - 100.
        """
        if not self.is_dimmable:
            raise SmartDeviceException("Device is not dimmable.")

        sys_info = self.sys_info
        return int(sys_info["brightness"])
Example #9
0
    async def set_brightness(self, brightness: int, *, transition: int = None) -> Dict:
        """Set the brightness in percentage.

        :param int brightness: brightness in percent
        :param int transition: transition in milliseconds.
        """
        if not self.is_dimmable:  # pragma: no cover
            raise SmartDeviceException("Bulb is not dimmable.")

        self._raise_for_invalid_brightness(brightness)

        light_state = {"brightness": brightness}
        return await self.set_light_state(light_state, transition=transition)
Example #10
0
    def hsv(self) -> Tuple[int, int, int]:
        """Return the current HSV state of the bulb.

        :return: hue, saturation and value (degrees, %, %)
        """
        if not self.is_color:
            raise SmartDeviceException("Bulb does not support color.")

        light_state = cast(dict, self.light_state)

        hue = light_state["hue"]
        saturation = light_state["saturation"]
        value = light_state["brightness"]

        return hue, saturation, value
Example #11
0
    def light_state(self) -> Dict[str, str]:
        """Query the light state."""
        light_state = self._last_update["system"]["get_sysinfo"]["light_state"]
        if light_state is None:
            raise SmartDeviceException(
                "The device has no light_state or you have not called update()"
            )

        # if the bulb is off, its state is stored under a different key
        # as is_on property depends on on_off itself, we check it here manually
        is_on = light_state["on_off"]
        if not is_on:
            off_state = {**light_state["dft_on_state"], "on_off": is_on}
            return cast(dict, off_state)

        return light_state
Example #12
0
    async def discover_single(host: str) -> SmartDevice:
        """Discover a single device by the given IP address.

        :param host: Hostname of device to query
        :rtype: SmartDevice
        :return: Object for querying/controlling found device.
        """
        protocol = AztechSmartHomeProtocol()

        info = await protocol.query(host, Discover.DISCOVERY_QUERY)

        device_class = Discover._get_device_class(info)
        if device_class is not None:
            dev = device_class(host)
            await dev.update()
            return dev

        raise SmartDeviceException("Unable to discover device, received: %s" %
                                   info)
Example #13
0
    async def set_color_temp(
        self, temp: int, *, brightness=None, transition: int = None
    ) -> Dict:
        """Set the color temperature of the device in kelvin.

        :param int temp: The new color temperature, in Kelvin
        :param int transition: transition in milliseconds.
        """
        if not self.is_variable_color_temp:
            raise SmartDeviceException("Bulb does not support colortemp.")

        valid_temperature_range = self.valid_temperature_range
        if temp < valid_temperature_range[0] or temp > valid_temperature_range[1]:
            raise ValueError(
                "Temperature should be between {} "
                "and {}".format(*valid_temperature_range)
            )

        light_state = {"color_temp": temp}
        if brightness is not None:
            light_state["brightness"] = brightness

        return await self.set_light_state(light_state, transition=transition)