Optimize I/O access (#59)

* Optimize I/O access

A single update() will now fetch information from all interesting modules,
including the current device state and the emeter information.

In practice, this will allow dropping the number of I/O reqs per homeassistant update cycle to 1,
which is paramount at least for bulbs which are very picky about sequential accesses.
This can be further extend to other modules/methods, if needed.

Currently fetched data:
* sysinfo
* realtime, today's and this months emeter stats

New properties:
* emeter_realtime: return the most recent emeter information, update()-version of get_emeter_realtime()
* emeter_today: returning today's energy consumption
* emeter_this_month: same for this month

Other changes:
* Accessing @requires_update properties will cause SmartDeviceException if the device has not ever been update()d
* Fix __repr__ for devices that haven't been updated
* Smartbulb uses now the state data from get_sysinfo instead of separately querying the bulb service
* SmartStrip's state_information no longer lists onsince for separate plugs
* The above mentioned properties are now printed out by cli
* Simplify is_on handling for bulbs

* remove implicit updates, return device responses for actions, update README.md instructions. fixes #61
This commit is contained in:
Teemu R
2020-05-24 17:57:54 +02:00
committed by GitHub
parent 012436c494
commit 836f1701b9
10 changed files with 201 additions and 101 deletions

View File

@@ -313,9 +313,7 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol):
def transition_light_state(self, x, *args):
_LOGGER.debug("Setting light state to %s", x)
light_state = self.proto["smartlife.iot.smartbulb.lightingservice"][
"get_light_state"
]
light_state = self.proto["system"]["get_sysinfo"]["light_state"]
# The required change depends on the light state,
# exception being turning the bulb on and off
@@ -323,15 +321,11 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol):
if x["on_off"] and not light_state["on_off"]: # turning on
new_state = light_state["dft_on_state"]
new_state["on_off"] = 1
self.proto["smartlife.iot.smartbulb.lightingservice"][
"get_light_state"
] = new_state
self.proto["system"]["get_sysinfo"]["light_state"] = new_state
elif not x["on_off"] and light_state["on_off"]:
new_state = {"dft_on_state": light_state, "on_off": 0}
self.proto["smartlife.iot.smartbulb.lightingservice"][
"get_light_state"
] = new_state
self.proto["system"]["get_sysinfo"]["light_state"] = new_state
return
@@ -343,11 +337,9 @@ class FakeTransportProtocol(TPLinkSmartHomeProtocol):
light_state[key] = x[key]
def light_state(self, x, *args):
light_state = self.proto["smartlife.iot.smartbulb.lightingservice"][
"get_light_state"
]
light_state = self.proto["system"]["get_sysinfo"]["light_state"]
# Our tests have light state off, so we simply return the dft_on_state when device is on.
_LOGGER.info("reporting light state: %s", light_state)
_LOGGER.debug("reporting light state: %s", light_state)
if light_state["on_off"]:
return light_state["dft_on_state"]
else:

View File

@@ -66,7 +66,7 @@ async def test_emeter(dev: SmartDevice, mocker):
assert "Device has no emeter" in res.output
return
assert "Current State" in res.output
assert "== Emeter ==" in res.output
monthly = mocker.patch.object(dev, "get_emeter_monthly")
res = await runner.invoke(emeter, ["--year", "1900"], obj=dev)

View File

@@ -419,9 +419,11 @@ async def test_children_alias(dev):
for plug in dev.plugs:
original = plug.alias
await plug.set_alias(alias=test_alias)
await dev.update() # TODO: set_alias does not call parent's update()..
assert plug.alias == test_alias
await plug.set_alias(alias=original)
await dev.update() # TODO: set_alias does not call parent's update()..
assert plug.alias == original