mirror of
				https://github.com/python-kasa/python-kasa.git
				synced 2025-11-04 14:42:09 +00:00 
			
		
		
		
	Merge pull request #135 from rytilahti/add_hs220_tests
Add tests and pretty output for HS220, fix minor issues in tests
This commit is contained in:
		@@ -15,6 +15,7 @@ Python Library to control TPLink smart plugs/switches and smart bulbs.
 | 
			
		||||
* Wall switches
 | 
			
		||||
  * HS200
 | 
			
		||||
  * HS210
 | 
			
		||||
  * HS220
 | 
			
		||||
* Bulbs
 | 
			
		||||
  * LB100
 | 
			
		||||
  * LB110
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,6 @@ pass_dev = click.make_pass_decorator(SmartDevice)
 | 
			
		||||
              help='The host name or IP address of the device to connect to.')
 | 
			
		||||
@click.option('--alias', envvar="PYHS100_NAME", required=False,
 | 
			
		||||
              help='The device name, or alias, of the device to connect to.')
 | 
			
		||||
 | 
			
		||||
@click.option('--debug/--normal', default=False)
 | 
			
		||||
@click.option('--bulb', default=False, is_flag=True)
 | 
			
		||||
@click.option('--plug', default=False, is_flag=True)
 | 
			
		||||
@@ -183,7 +182,10 @@ def emeter(dev, year, month, erase):
 | 
			
		||||
                required=False)
 | 
			
		||||
@pass_dev
 | 
			
		||||
def brightness(dev, brightness):
 | 
			
		||||
    """Get or set brightness. (Bulb Only)"""
 | 
			
		||||
    """Get or set brightness."""
 | 
			
		||||
    if not dev.is_dimmable:
 | 
			
		||||
        click.echo("This device does not support brightness.")
 | 
			
		||||
        return
 | 
			
		||||
    if brightness is None:
 | 
			
		||||
        click.echo("Brightness: %s" % dev.brightness)
 | 
			
		||||
    else:
 | 
			
		||||
@@ -263,5 +265,6 @@ def reboot(plug, delay):
 | 
			
		||||
    click.echo("Rebooting the device..")
 | 
			
		||||
    plug.reboot(delay)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    cli()
 | 
			
		||||
 
 | 
			
		||||
@@ -119,6 +119,9 @@ class SmartDevice(object):
 | 
			
		||||
            raise SmartDeviceException("Error on {}.{}: {}"
 | 
			
		||||
                                       .format(target, cmd, result))
 | 
			
		||||
 | 
			
		||||
        if cmd not in result:
 | 
			
		||||
            raise SmartDeviceException("No command in response: {}"
 | 
			
		||||
                                       .format(response))
 | 
			
		||||
        result = result[cmd]
 | 
			
		||||
        del result["err_code"]
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -107,7 +107,7 @@ class SmartPlug(SmartDevice):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        if not self.is_dimmable:
 | 
			
		||||
            return None
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if not isinstance(value, int):
 | 
			
		||||
            raise ValueError("Brightness must be integer, "
 | 
			
		||||
@@ -128,10 +128,7 @@ class SmartPlug(SmartDevice):
 | 
			
		||||
        :rtype: bool
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        dimmable = False
 | 
			
		||||
        if "brightness" in self.sys_info:
 | 
			
		||||
            dimmable = True
 | 
			
		||||
        return dimmable
 | 
			
		||||
        return "brightness" in self.sys_info
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def has_emeter(self):
 | 
			
		||||
@@ -201,7 +198,16 @@ class SmartPlug(SmartDevice):
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def state_information(self) -> Dict[str, Any]:
 | 
			
		||||
        return {
 | 
			
		||||
        """
 | 
			
		||||
        Return switch-specific state information.
 | 
			
		||||
 | 
			
		||||
        :return: Switch information dict, keys in user-presentable form.
 | 
			
		||||
        :rtype: dict
 | 
			
		||||
        """
 | 
			
		||||
        info = {
 | 
			
		||||
            'LED state': self.led,
 | 
			
		||||
            'On since': self.on_since
 | 
			
		||||
        }
 | 
			
		||||
        if self.is_dimmable:
 | 
			
		||||
            info["Brightness"] = self.brightness
 | 
			
		||||
        return info
 | 
			
		||||
 
 | 
			
		||||
@@ -165,6 +165,44 @@ sysinfo_hs200 = {'system': {'get_sysinfo': {'active_mode': 'schedule',
 | 
			
		||||
                            'updating': 0}}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sysinfo_hs220 = {
 | 
			
		||||
    "system": {
 | 
			
		||||
        "get_sysinfo": {
 | 
			
		||||
            "sw_ver": "1.4.8 Build 180109 Rel.171240",
 | 
			
		||||
            "hw_ver": "1.0",
 | 
			
		||||
            "mic_type": "IOT.SMARTPLUGSWITCH",
 | 
			
		||||
            "model": "HS220(US)",
 | 
			
		||||
            "mac": "B0:4E:26:11:22:33",
 | 
			
		||||
            "dev_name": "Smart Wi-Fi Dimmer",
 | 
			
		||||
            "alias": "Chandelier",
 | 
			
		||||
            "relay_state": 0,
 | 
			
		||||
            "brightness": 25,
 | 
			
		||||
            "on_time": 0,
 | 
			
		||||
            "active_mode": "none",
 | 
			
		||||
            "feature": "TIM",
 | 
			
		||||
            "updating": 0,
 | 
			
		||||
            "icon_hash": "",
 | 
			
		||||
            "rssi": -53,
 | 
			
		||||
            "led_off": 0,
 | 
			
		||||
            "longitude_i": -12.2,
 | 
			
		||||
            "latitude_i": 12.2,
 | 
			
		||||
            "hwId": "84DCCF37225C9E55319617F7D5C095BD",
 | 
			
		||||
            "fwId": "00000000000000000000000000000000",
 | 
			
		||||
            "deviceId": "800695154E6B882428E30F850473F34019A9E999",
 | 
			
		||||
            "oemId": "3B13224B2807E0D48A9DD06EBD344CD6",
 | 
			
		||||
            "preferred_state":
 | 
			
		||||
                [
 | 
			
		||||
                    {"index": 0, "brightness": 100},
 | 
			
		||||
                    {"index": 1, "brightness": 75},
 | 
			
		||||
                    {"index": 2, "brightness": 50},
 | 
			
		||||
                    {"index": 3, "brightness": 25}
 | 
			
		||||
                ],
 | 
			
		||||
            "next_action": {"type": -1},
 | 
			
		||||
            "err_code": 0
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sysinfo_lb130 = {'system': {'get_sysinfo':
 | 
			
		||||
                    {'active_mode': 'none',
 | 
			
		||||
                     'alias': 'Living Room Side Table',
 | 
			
		||||
@@ -423,7 +461,7 @@ sysinfo_lb120 = {'system':
 | 
			
		||||
                 }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def error(cls, target, cmd="no-command", msg="default msg"):
 | 
			
		||||
def error(target, cmd="no-command", msg="default msg"):
 | 
			
		||||
    return {target: {cmd: {"err_code": -1323, "msg": msg}}}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -460,7 +498,11 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol):
 | 
			
		||||
 | 
			
		||||
    def set_mac(self, x):
 | 
			
		||||
        _LOGGER.debug("Setting mac to %s", x)
 | 
			
		||||
        self.proto["system"]["get_sysinfo"][""]
 | 
			
		||||
        self.proto["system"]["get_sysinfo"]["mac"] = x
 | 
			
		||||
 | 
			
		||||
    def set_hs220_brightness(self, x):
 | 
			
		||||
        _LOGGER.debug("Setting brightness to %s", x)
 | 
			
		||||
        self.proto["system"]["get_sysinfo"]["brightness"] = x["brightness"]
 | 
			
		||||
 | 
			
		||||
    def transition_light_state(self, x):
 | 
			
		||||
        _LOGGER.debug("Setting light state to %s", x)
 | 
			
		||||
@@ -491,8 +533,10 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol):
 | 
			
		||||
        "time": { "get_time": { "year": 2017, "month": 1, "mday": 2, "hour": 3, "min": 4, "sec": 5 },
 | 
			
		||||
                  "get_timezone": {'zone_str': "test", 'dst_offset': -1, 'index': 12, 'tz_str': "test2" },
 | 
			
		||||
                  "set_timezone": None,
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        },
 | 
			
		||||
        # HS220 brightness, different setter and getter
 | 
			
		||||
        "smartlife.iot.dimmer": { "set_brightness": set_hs220_brightness,
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    def query(self, host, request, port=9999):
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,9 @@ from .fakes import (FakeTransportProtocol,
 | 
			
		||||
                    sysinfo_hs105,
 | 
			
		||||
                    sysinfo_hs110,
 | 
			
		||||
                    sysinfo_hs110_au_v2,
 | 
			
		||||
                    sysinfo_hs200)
 | 
			
		||||
                    sysinfo_hs200,
 | 
			
		||||
                    sysinfo_hs220,
 | 
			
		||||
                    )
 | 
			
		||||
 | 
			
		||||
# Set IP instead of None if you want to run tests on a device.
 | 
			
		||||
PLUG_IP = None
 | 
			
		||||
@@ -66,6 +68,14 @@ class TestSmartPlugHS100(TestCase):
 | 
			
		||||
        'type': str,
 | 
			
		||||
        'mic_type': str,
 | 
			
		||||
        'updating': check_int_bool,
 | 
			
		||||
        # these are available on hs220
 | 
			
		||||
        'brightness': int,
 | 
			
		||||
        'preferred_state': [{
 | 
			
		||||
            'brightness': All(int, Range(min=0, max=100)),
 | 
			
		||||
            'index': int,
 | 
			
		||||
        }],
 | 
			
		||||
        "next_action": {"type": int},
 | 
			
		||||
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    current_consumption_schema = Schema(Any({
 | 
			
		||||
@@ -335,3 +345,26 @@ class TestSmartPlugHS105(TestSmartPlugHS100):
 | 
			
		||||
                               protocol=FakeTransportProtocol(self.SYSINFO))
 | 
			
		||||
 | 
			
		||||
        self.sysinfo_schema(plug_i.location)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestSmartPlugHS220(TestSmartPlugHS105):
 | 
			
		||||
    """HS220 with dimming functionality. Sysinfo looks similar to HS105."""
 | 
			
		||||
    SYSINFO = sysinfo_hs220
 | 
			
		||||
 | 
			
		||||
    def test_dimmable(self):
 | 
			
		||||
        assert self.plug.is_dimmable
 | 
			
		||||
        assert self.plug.brightness == 25
 | 
			
		||||
        self.plug.brightness = 100
 | 
			
		||||
        assert self.plug.brightness == 100
 | 
			
		||||
 | 
			
		||||
        with self.assertRaises(ValueError):
 | 
			
		||||
            self.plug.brightness = 110
 | 
			
		||||
 | 
			
		||||
        with self.assertRaises(ValueError):
 | 
			
		||||
            self.plug.brightness = -1
 | 
			
		||||
 | 
			
		||||
        with self.assertRaises(ValueError):
 | 
			
		||||
            self.plug.brightness = "foo"
 | 
			
		||||
 | 
			
		||||
        with self.assertRaises(ValueError):
 | 
			
		||||
            self.plug.brightness = 11.1
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user