diff --git a/.codeclimate.yml b/.codeclimate.yml
index feded49..c0db768 100644
--- a/.codeclimate.yml
+++ b/.codeclimate.yml
@@ -1,5 +1,8 @@
version: "2"
checks:
+ argument-count:
+ config:
+ threshold: 5
method-complexity:
config:
threshold: 13
diff --git a/pyfritzhome/devicetypes/fritzhomedeviceblind.py b/pyfritzhome/devicetypes/fritzhomedeviceblind.py
index 5f728b2..fc11d62 100644
--- a/pyfritzhome/devicetypes/fritzhomedeviceblind.py
+++ b/pyfritzhome/devicetypes/fritzhomedeviceblind.py
@@ -38,14 +38,14 @@ def _update_blind_from_node(self, node):
except Exception:
pass
- def set_blind_open(self):
+ def set_blind_open(self, wait=False):
"""Open the blind."""
- self._fritz.set_blind_open(self.ain)
+ self._fritz.set_blind_open(self.ain, wait)
- def set_blind_close(self):
+ def set_blind_close(self, wait=False):
"""Close the blind."""
- self._fritz.set_blind_close(self.ain)
+ self._fritz.set_blind_close(self.ain, wait)
- def set_blind_stop(self):
+ def set_blind_stop(self, wait=False):
"""Stop the blind."""
- self._fritz.set_blind_stop(self.ain)
+ self._fritz.set_blind_stop(self.ain, wait)
diff --git a/pyfritzhome/devicetypes/fritzhomedevicelevel.py b/pyfritzhome/devicetypes/fritzhomedevicelevel.py
index 5b08955..3e8fcf5 100644
--- a/pyfritzhome/devicetypes/fritzhomedevicelevel.py
+++ b/pyfritzhome/devicetypes/fritzhomedevicelevel.py
@@ -48,10 +48,10 @@ def get_level_percentage(self):
"""Get the level in percentage."""
return self.levelpercentage
- def set_level(self, level):
+ def set_level(self, level, wait=False):
"""Set the level."""
- self._fritz.set_level(self.ain, level)
+ self._fritz.set_level(self.ain, level, wait)
- def set_level_percentage(self, levelpercentage):
+ def set_level_percentage(self, levelpercentage, wait=False):
"""Set the level in percentage."""
- self._fritz.set_level_percentage(self.ain, levelpercentage)
+ self._fritz.set_level_percentage(self.ain, levelpercentage, wait)
diff --git a/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py b/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py
index 8d085d5..2dbe4aa 100644
--- a/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py
+++ b/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py
@@ -91,20 +91,20 @@ def _update_lightbulb_from_node(self, node):
# reset values after color mode changed
self.color_temp = None
- def set_state_off(self):
+ def set_state_off(self, wait=False):
"""Switch light bulb off."""
self.state = True
- self._fritz.set_state_off(self.ain)
+ self._fritz.set_state_off(self.ain, wait)
- def set_state_on(self):
+ def set_state_on(self, wait=False):
"""Switch light bulb on."""
self.state = True
- self._fritz.set_state_on(self.ain)
+ self._fritz.set_state_on(self.ain, wait)
- def set_state_toggle(self):
+ def set_state_toggle(self, wait=False):
"""Toogle light bulb state."""
self.state = True
- self._fritz.set_state_toggle(self.ain)
+ self._fritz.set_state_toggle(self.ain, wait)
def get_colors(self):
"""Get the supported colors."""
@@ -113,15 +113,15 @@ def get_colors(self):
else:
return {}
- def set_color(self, hsv, duration=0):
+ def set_color(self, hsv, duration=0, wait=False):
"""Set HSV color."""
if self.has_color:
- self._fritz.set_color(self.ain, hsv, duration, True)
+ self._fritz.set_color(self.ain, hsv, duration, True, wait)
- def set_unmapped_color(self, hsv, duration=0):
+ def set_unmapped_color(self, hsv, duration=0, wait=False):
"""Set unmapped HSV color (Free color selection)."""
if self.has_color:
- self._fritz.set_color(self.ain, hsv, duration, False)
+ self._fritz.set_color(self.ain, hsv, duration, False, wait)
def get_color_temps(self):
"""Get the supported color temperatures energy."""
@@ -130,7 +130,7 @@ def get_color_temps(self):
else:
return []
- def set_color_temp(self, temperature, duration=0):
+ def set_color_temp(self, temperature, duration=0, wait=False):
"""Set white color temperature."""
if self.has_color:
- self._fritz.set_color_temp(self.ain, temperature, duration)
+ self._fritz.set_color_temp(self.ain, temperature, duration, wait)
diff --git a/pyfritzhome/devicetypes/fritzhomedeviceswitch.py b/pyfritzhome/devicetypes/fritzhomedeviceswitch.py
index 9df1fb0..92f1de3 100644
--- a/pyfritzhome/devicetypes/fritzhomedeviceswitch.py
+++ b/pyfritzhome/devicetypes/fritzhomedeviceswitch.py
@@ -68,14 +68,14 @@ def get_switch_state(self):
"""Get the switch state."""
return self._fritz.get_switch_state(self.ain)
- def set_switch_state_on(self):
+ def set_switch_state_on(self, wait=False):
"""Set the switch state to on."""
- return self._fritz.set_switch_state_on(self.ain)
+ return self._fritz.set_switch_state_on(self.ain, wait)
- def set_switch_state_off(self):
+ def set_switch_state_off(self, wait=False):
"""Set the switch state to off."""
- return self._fritz.set_switch_state_off(self.ain)
+ return self._fritz.set_switch_state_off(self.ain, wait)
- def set_switch_state_toggle(self):
+ def set_switch_state_toggle(self, wait=False):
"""Toggle the switch state."""
- return self._fritz.set_switch_state_toggle(self.ain)
+ return self._fritz.set_switch_state_toggle(self.ain, wait)
diff --git a/pyfritzhome/devicetypes/fritzhomedevicethermostat.py b/pyfritzhome/devicetypes/fritzhomedevicethermostat.py
index 189a4f4..29c8ebd 100644
--- a/pyfritzhome/devicetypes/fritzhomedevicethermostat.py
+++ b/pyfritzhome/devicetypes/fritzhomedevicethermostat.py
@@ -132,17 +132,17 @@ def get_target_temperature(self):
"""Get the thermostate target temperature."""
return self._fritz.get_target_temperature(self.ain)
- def set_target_temperature(self, temperature):
+ def set_target_temperature(self, temperature, wait=False):
"""Set the thermostate target temperature."""
- return self._fritz.set_target_temperature(self.ain, temperature)
+ return self._fritz.set_target_temperature(self.ain, temperature, wait)
- def set_window_open(self, seconds):
+ def set_window_open(self, seconds, wait=False):
"""Set the thermostate to window open."""
- return self._fritz.set_window_open(self.ain, seconds)
+ return self._fritz.set_window_open(self.ain, seconds, wait)
- def set_boost_mode(self, seconds):
+ def set_boost_mode(self, seconds, wait=False):
"""Set the thermostate into boost mode."""
- return self._fritz.set_boost_mode(self.ain, seconds)
+ return self._fritz.set_boost_mode(self.ain, seconds, wait)
def get_comfort_temperature(self):
"""Get the thermostate comfort temperature."""
@@ -164,7 +164,7 @@ def get_hkr_state(self):
except KeyError:
return "manual"
- def set_hkr_state(self, state):
+ def set_hkr_state(self, state, wait=False):
"""Set the state of the thermostat.
Possible values for state are: 'on', 'off', 'comfort', 'eco'.
@@ -179,4 +179,4 @@ def set_hkr_state(self, state):
except KeyError:
return
- self.set_target_temperature(value)
+ self.set_target_temperature(value, wait)
diff --git a/pyfritzhome/fritzhome.py b/pyfritzhome/fritzhome.py
index d57420b..43e1b51 100644
--- a/pyfritzhome/fritzhome.py
+++ b/pyfritzhome/fritzhome.py
@@ -197,6 +197,17 @@ def _get_listinfo_elements(self, entity_type):
_LOGGER.debug(dom)
return dom.findall("*")
+ def wait_device_txbusy(self, ain, retries=10):
+ """Wait for device to finish command execution."""
+ for _ in range(retries):
+ plain = self.get_device_infos(ain)
+ dom = ElementTree.fromstring(plain)
+ txbusy = dom.findall("txbusy")
+ if txbusy[0].text == "0":
+ return True
+ time.sleep(0.2)
+ return False
+
def get_device_elements(self):
"""Get the DOM elements for the device list."""
return self._get_listinfo_elements("device")
@@ -223,6 +234,10 @@ def get_device_by_ain(self, ain):
"""Return a device specified by the AIN."""
return self.get_devices_as_dict()[ain]
+ def get_device_infos(self, ain):
+ """Get the device infos."""
+ return self._aha_request("getdeviceinfos", ain=ain)
+
def get_device_present(self, ain):
"""Get the device presence."""
return self._aha_request("getswitchpresent", ain=ain, rf=bool)
@@ -235,17 +250,23 @@ def get_switch_state(self, ain):
"""Get the switch state."""
return self._aha_request("getswitchstate", ain=ain, rf=bool)
- def set_switch_state_on(self, ain):
+ def set_switch_state_on(self, ain, wait=False):
"""Set the switch to on state."""
- return self._aha_request("setswitchon", ain=ain, rf=bool)
+ result = self._aha_request("setswitchon", ain=ain, rf=bool)
+ wait and self.wait_device_txbusy(ain)
+ return result
- def set_switch_state_off(self, ain):
+ def set_switch_state_off(self, ain, wait=False):
"""Set the switch to off state."""
- return self._aha_request("setswitchoff", ain=ain, rf=bool)
+ result = self._aha_request("setswitchoff", ain=ain, rf=bool)
+ wait and self.wait_device_txbusy(ain)
+ return result
- def set_switch_state_toggle(self, ain):
+ def set_switch_state_toggle(self, ain, wait=False):
"""Toggle the switch state."""
- return self._aha_request("setswitchtoggle", ain=ain, rf=bool)
+ result = self._aha_request("setswitchtoggle", ain=ain, rf=bool)
+ wait and self.wait_device_txbusy(ain)
+ return result
def get_switch_power(self, ain):
"""Get the switch power consumption."""
@@ -267,7 +288,7 @@ def get_target_temperature(self, ain):
"""Get the thermostate target temperature."""
return self._get_temperature(ain, "gethkrtsoll")
- def set_target_temperature(self, ain, temperature):
+ def set_target_temperature(self, ain, temperature, wait=False):
"""Set the thermostate target temperature."""
temp = int(16 + ((float(temperature) - 8) * 2))
@@ -277,20 +298,23 @@ def set_target_temperature(self, ain, temperature):
temp = 254
self._aha_request("sethkrtsoll", ain=ain, param={"param": temp})
+ wait and self.wait_device_txbusy(ain)
- def set_window_open(self, ain, seconds):
+ def set_window_open(self, ain, seconds, wait=False):
"""Set the thermostate target temperature."""
endtimestamp = int(time.time() + seconds)
self._aha_request(
"sethkrwindowopen", ain=ain, param={"endtimestamp": endtimestamp}
)
+ wait and self.wait_device_txbusy(ain)
- def set_boost_mode(self, ain, seconds):
+ def set_boost_mode(self, ain, seconds, wait=False):
"""Set the thermostate to boost mode."""
endtimestamp = int(time.time() + seconds)
self._aha_request("sethkrboost", ain=ain, param={"endtimestamp": endtimestamp})
+ wait and self.wait_device_txbusy(ain)
def get_comfort_temperature(self, ain):
"""Get the thermostate comfort temperature."""
@@ -307,19 +331,22 @@ def get_device_statistics(self, ain):
# Lightbulb-related commands
- def set_state_off(self, ain):
+ def set_state_off(self, ain, wait=False):
"""Set the switch/actuator/lightbulb to on state."""
self._aha_request("setsimpleonoff", ain=ain, param={"onoff": 0})
+ wait and self.wait_device_txbusy(ain)
- def set_state_on(self, ain):
+ def set_state_on(self, ain, wait=False):
"""Set the switch/actuator/lightbulb to on state."""
self._aha_request("setsimpleonoff", ain=ain, param={"onoff": 1})
+ wait and self.wait_device_txbusy(ain)
- def set_state_toggle(self, ain):
+ def set_state_toggle(self, ain, wait=False):
"""Toggle the switch/actuator/lightbulb state."""
self._aha_request("setsimpleonoff", ain=ain, param={"onoff": 2})
+ wait and self.wait_device_txbusy(ain)
- def set_level(self, ain, level):
+ def set_level(self, ain, level, wait=False):
"""Set level/brightness/height in interval [0,255]."""
if level < 0:
level = 0 # 0%
@@ -327,8 +354,9 @@ def set_level(self, ain, level):
level = 255 # 100 %
self._aha_request("setlevel", ain=ain, param={"level": int(level)})
+ wait and self.wait_device_txbusy(ain)
- def set_level_percentage(self, ain, level):
+ def set_level_percentage(self, ain, level, wait=False):
"""Set level/brightness/height in interval [0,100]."""
if level < 0:
level = 0
@@ -336,6 +364,7 @@ def set_level_percentage(self, ain, level):
level = 100
self._aha_request("setlevelpercentage", ain=ain, param={"level": int(level)})
+ wait and self.wait_device_txbusy(ain)
def _get_colordefaults(self, ain):
plain = self._aha_request("getcolordefaults", ain=ain)
@@ -353,7 +382,7 @@ def get_colors(self, ain):
colors[name] = values
return colors
- def set_color(self, ain, hsv, duration=0, mapped=True):
+ def set_color(self, ain, hsv, duration=0, mapped=True, wait=False):
"""Set hue and saturation.
hsv: HUE colorspace element obtained from get_colors()
@@ -369,6 +398,7 @@ def set_color(self, ain, hsv, duration=0, mapped=True):
else:
# undocumented API method for free color selection
self._aha_request("setunmappedcolor", ain=ain, param=params)
+ wait and self.wait_device_txbusy(ain)
def get_color_temps(self, ain):
"""Get temperatures supported by this lightbulb."""
@@ -378,7 +408,7 @@ def get_color_temps(self, ain):
temperatures.append(temp.get("value"))
return temperatures
- def set_color_temp(self, ain, temperature, duration=0):
+ def set_color_temp(self, ain, temperature, duration=0, wait=False):
"""Set color temperature.
temperature: temperature element obtained from get_temperatures()
@@ -386,23 +416,27 @@ def set_color_temp(self, ain, temperature, duration=0):
"""
params = {"temperature": int(temperature), "duration": int(duration) * 10}
self._aha_request("setcolortemperature", ain=ain, param=params)
+ wait and self.wait_device_txbusy(ain)
# blinds
# states: open, close, stop
def _set_blind_state(self, ain, state):
self._aha_request("setblind", ain=ain, param={"target": state})
- def set_blind_open(self, ain):
+ def set_blind_open(self, ain, wait=False):
"""Set the blind state to open."""
self._set_blind_state(ain, "open")
+ wait and self.wait_device_txbusy(ain)
- def set_blind_close(self, ain):
+ def set_blind_close(self, ain, wait=False):
"""Set the blind state to close."""
self._set_blind_state(ain, "close")
+ wait and self.wait_device_txbusy(ain)
- def set_blind_stop(self, ain):
+ def set_blind_stop(self, ain, wait=False):
"""Set the blind state to stop."""
self._set_blind_state(ain, "stop")
+ wait and self.wait_device_txbusy(ain)
# Template-related commands
diff --git a/tests/responses/base/device_not_txbusy.xml b/tests/responses/base/device_not_txbusy.xml
new file mode 100644
index 0000000..3b7fc48
--- /dev/null
+++ b/tests/responses/base/device_not_txbusy.xml
@@ -0,0 +1,24 @@
+
+
+ 0
+ 0
+ Kitchen
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+ 0
+ 255
+
+
+
\ No newline at end of file
diff --git a/tests/responses/base/device_txbusy.xml b/tests/responses/base/device_txbusy.xml
new file mode 100644
index 0000000..5d7e4e5
--- /dev/null
+++ b/tests/responses/base/device_txbusy.xml
@@ -0,0 +1,24 @@
+
+
+ 0
+ 1
+ Kitchen
+
+
+
+
+
+
+
+
+
+
+
+ 0
+ 0
+
+ 0
+ 255
+
+
+
\ No newline at end of file
diff --git a/tests/test_fritzhome.py b/tests/test_fritzhome.py
index 7233870..4f87976 100644
--- a/tests/test_fritzhome.py
+++ b/tests/test_fritzhome.py
@@ -240,3 +240,19 @@ def test_set_boost_mode(self):
"endtimestamp": 1000 + 25,
},
)
+
+ def test_wait_tx_busy(self):
+ self.mock.side_effect = [
+ Helper.response("base/device_txbusy"),
+ Helper.response("base/device_not_txbusy"),
+ ]
+
+ assert self.fritz.wait_device_txbusy("11960 0089208")
+
+ def test_wait_tx_busy_failed(self):
+ self.mock.side_effect = [
+ Helper.response("base/device_txbusy"),
+ Helper.response("base/device_txbusy"),
+ ]
+
+ assert not self.fritz.wait_device_txbusy("11960 0089208", 1)