mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-10-10 17:38:01 +00:00
Fix emeter support for newer HS110 firmwares (#107)
* Add support for new-style emeter This commit adds a straightforward dict-extending container, which converts between the old and new keys of the get_emeter_realtime() Furthermore the unit tests are converted to base on HS100 instead of HS110. This is the first step to fix #103, other emeter-using functionality has not yet been converted, only getting the current consumption. * fix a couple of linting issues * Convert new-style emeter values also for get_emeter_daily() and get_emeter_monthly() * Adds a new 'kwh' parameter for those calls, which defaults to True * This changes the behavior of bulbs emeter reporting, use False if you prefer the preciser values
This commit is contained in:
@@ -113,9 +113,34 @@ sysinfo_hs110 = {'system': {'get_sysinfo':
|
||||
'type': 'IOT.SMARTPLUGSWITCH',
|
||||
'updating': 0}
|
||||
},
|
||||
"emeter": emeter_support,
|
||||
'emeter': emeter_support,
|
||||
}
|
||||
|
||||
sysinfo_hs110_au_v2 = {'system': {'get_sysinfo':
|
||||
{'active_mode': 'none',
|
||||
'alias': 'Tplink Test',
|
||||
'dev_name': 'Smart Wi-Fi Plug With Energy Monitoring',
|
||||
'deviceId': '80062952E2F3D9461CFB91FF21B7868F194F627A',
|
||||
'feature': 'TIM:ENE',
|
||||
'fwId': '00000000000000000000000000000000',
|
||||
'hwId': 'A28C8BB92AFCB6CAFB83A8C00145F7E2',
|
||||
'hw_ver': '2.0',
|
||||
'icon_hash': '',
|
||||
'latitude_i': -1.1,
|
||||
'led_off': 0,
|
||||
'longitude_i': 2.2,
|
||||
'mac': '70:4F:57:12:12:12',
|
||||
'model': 'HS110(AU)',
|
||||
'oemId': '6480C2101948463DC65D7009CAECDECC',
|
||||
'on_time': 0,
|
||||
'relay_state': 0,
|
||||
'rssi': -70,
|
||||
'sw_ver': '1.5.2 Build 171201 Rel.084625',
|
||||
'type': 'IOT.SMARTPLUGSWITCH',
|
||||
'updating': 0}
|
||||
},
|
||||
'emeter': {'voltage_mv': 246520, 'power_mw': 258401, 'current_ma': 3104, 'total_wh': 387}}
|
||||
|
||||
sysinfo_hs200 = {'system': {'get_sysinfo': {'active_mode': 'schedule',
|
||||
'alias': 'Christmas Tree Switch',
|
||||
'dev_name': 'Wi-Fi Smart Light Switch',
|
||||
|
@@ -156,18 +156,27 @@ class TestSmartBulb(TestCase):
|
||||
def test_get_emeter_daily(self):
|
||||
self.assertEqual(self.bulb.get_emeter_daily(year=1900, month=1), {})
|
||||
|
||||
k, v = self.bulb.get_emeter_daily().popitem()
|
||||
k, v = self.bulb.get_emeter_daily(kwh=False).popitem()
|
||||
self.assertTrue(isinstance(k, int))
|
||||
self.assertTrue(isinstance(v, int))
|
||||
|
||||
k, v = self.bulb.get_emeter_daily(kwh=True).popitem()
|
||||
self.assertTrue(isinstance(k, int))
|
||||
self.assertTrue(isinstance(v, float))
|
||||
|
||||
def test_get_emeter_monthly(self):
|
||||
self.assertEqual(self.bulb.get_emeter_monthly(year=1900), {})
|
||||
|
||||
d = self.bulb.get_emeter_monthly()
|
||||
d = self.bulb.get_emeter_monthly(kwh=False)
|
||||
k, v = d.popitem()
|
||||
self.assertTrue(isinstance(k, int))
|
||||
self.assertTrue(isinstance(v, int))
|
||||
|
||||
d = self.bulb.get_emeter_monthly(kwh=True)
|
||||
k, v = d.popitem()
|
||||
self.assertTrue(isinstance(k, int))
|
||||
self.assertTrue(isinstance(v, float))
|
||||
|
||||
@skip("not clearing your stats..")
|
||||
def test_erase_emeter_stats(self):
|
||||
self.fail()
|
||||
|
@@ -10,6 +10,7 @@ from .fakes import (FakeTransportProtocol,
|
||||
sysinfo_hs100,
|
||||
sysinfo_hs105,
|
||||
sysinfo_hs110,
|
||||
sysinfo_hs110_au_v2,
|
||||
sysinfo_hs200)
|
||||
|
||||
# Set IP instead of None if you want to run tests on a device.
|
||||
@@ -35,8 +36,8 @@ def check_mode(x):
|
||||
raise Invalid("invalid mode {}".format(x))
|
||||
|
||||
|
||||
class TestSmartPlugHS110(TestCase):
|
||||
SYSINFO = sysinfo_hs110 # type: Dict
|
||||
class TestSmartPlugHS100(TestCase):
|
||||
SYSINFO = sysinfo_hs100 # type: Dict
|
||||
# these schemas should go to the mainlib as
|
||||
# they can be useful when adding support for new features/devices
|
||||
# as well as to check that faked devices are operating properly.
|
||||
@@ -68,10 +69,15 @@ class TestSmartPlugHS110(TestCase):
|
||||
})
|
||||
|
||||
current_consumption_schema = Schema(Any({
|
||||
'voltage': All(float, Range(min=0, max=300)),
|
||||
'power': Coerce(float, Range(min=0)),
|
||||
'total': Coerce(float, Range(min=0)),
|
||||
'current': All(float, Range(min=0)),
|
||||
'voltage': Any(All(float, Range(min=0, max=300)), None),
|
||||
'power': Any(Coerce(float, Range(min=0)), None),
|
||||
'total': Any(Coerce(float, Range(min=0)), None),
|
||||
'current': Any(All(float, Range(min=0)), None),
|
||||
|
||||
'voltage_mw': Any(All(float, Range(min=0, max=300000)), None),
|
||||
'power_mw': Any(Coerce(float, Range(min=0)), None),
|
||||
'total_wh': Any(Coerce(float, Range(min=0)), None),
|
||||
'current_ma': Any(All(float, Range(min=0)), None),
|
||||
}, None))
|
||||
|
||||
tz_schema = Schema({
|
||||
@@ -210,11 +216,6 @@ class TestSmartPlugHS110(TestCase):
|
||||
else:
|
||||
self.assertEqual(self.plug.current_consumption(), None)
|
||||
|
||||
def test_identify(self):
|
||||
ident = self.plug.identify()
|
||||
self.assertTrue(isinstance(ident, tuple))
|
||||
self.assertTrue(len(ident) == 3)
|
||||
|
||||
def test_alias(self):
|
||||
test_alias = "TEST1234"
|
||||
original = self.plug.alias
|
||||
@@ -261,15 +262,69 @@ class TestSmartPlugHS110(TestCase):
|
||||
# TODO check setting?
|
||||
|
||||
|
||||
class TestSmartPlugHS100(TestSmartPlugHS110):
|
||||
SYSINFO = sysinfo_hs100
|
||||
class TestSmartPlugHS110(TestSmartPlugHS100):
|
||||
SYSINFO = sysinfo_hs110
|
||||
|
||||
def test_emeter_upcast(self):
|
||||
emeter = self.plug.get_emeter_realtime()
|
||||
self.assertAlmostEqual(emeter["power"] * 10**3, emeter["power_mw"])
|
||||
self.assertAlmostEqual(emeter["voltage"] * 10**3, emeter["voltage_mv"])
|
||||
self.assertAlmostEqual(emeter["current"] * 10**3, emeter["current_ma"])
|
||||
self.assertAlmostEqual(emeter["total"] * 10**3, emeter["total_wh"])
|
||||
|
||||
def test_emeter_daily_upcast(self):
|
||||
emeter = self.plug.get_emeter_daily()
|
||||
_, v = emeter.popitem()
|
||||
|
||||
emeter = self.plug.get_emeter_daily(kwh=False)
|
||||
_, v2 = emeter.popitem()
|
||||
|
||||
self.assertAlmostEqual(v * 10**3, v2)
|
||||
|
||||
def test_get_emeter_monthly_upcast(self):
|
||||
emeter = self.plug.get_emeter_monthly()
|
||||
_, v = emeter.popitem()
|
||||
|
||||
emeter = self.plug.get_emeter_monthly(kwh=False)
|
||||
_, v2 = emeter.popitem()
|
||||
|
||||
self.assertAlmostEqual(v * 10**3, v2)
|
||||
|
||||
|
||||
class TestSmartPlugHS200(TestSmartPlugHS110):
|
||||
class TestSmartPlugHS110_HW2(TestSmartPlugHS100):
|
||||
SYSINFO = sysinfo_hs110_au_v2
|
||||
|
||||
def test_emeter_downcast(self):
|
||||
emeter = self.plug.get_emeter_realtime()
|
||||
self.assertAlmostEqual(emeter["power"], emeter["power_mw"] / 10**3)
|
||||
self.assertAlmostEqual(emeter["voltage"], emeter["voltage_mv"] / 10**3)
|
||||
self.assertAlmostEqual(emeter["current"], emeter["current_ma"] / 10**3)
|
||||
self.assertAlmostEqual(emeter["total"], emeter["total_wh"] / 10**3)
|
||||
|
||||
def test_emeter_daily_downcast(self):
|
||||
emeter = self.plug.get_emeter_daily()
|
||||
_, v = emeter.popitem()
|
||||
|
||||
emeter = self.plug.get_emeter_daily(kwh=False)
|
||||
_, v2 = emeter.popitem()
|
||||
|
||||
self.assertAlmostEqual(v * 10**3, v2)
|
||||
|
||||
def test_get_emeter_monthly_downcast(self):
|
||||
emeter = self.plug.get_emeter_monthly()
|
||||
_, v = emeter.popitem()
|
||||
|
||||
emeter = self.plug.get_emeter_monthly(kwh=False)
|
||||
_, v2 = emeter.popitem()
|
||||
|
||||
self.assertAlmostEqual(v * 10**3, v2)
|
||||
|
||||
|
||||
class TestSmartPlugHS200(TestSmartPlugHS100):
|
||||
SYSINFO = sysinfo_hs200
|
||||
|
||||
|
||||
class TestSmartPlugHS105(TestSmartPlugHS110):
|
||||
class TestSmartPlugHS105(TestSmartPlugHS100):
|
||||
SYSINFO = sysinfo_hs105
|
||||
|
||||
def test_location_i(self):
|
||||
|
Reference in New Issue
Block a user