diff --git a/README.rst b/README.rst
index 37ed83e..7e6d5c8 100644
--- a/README.rst
+++ b/README.rst
@@ -13,8 +13,10 @@ Tested Devices
* `Panasonic KX-HNS101`
* `Magenta Smarthome Tür-/Fensterkontakt optisch`_
* `RADEMACHER RolloTron DECT 1213`_
-
-
+* `Magenta Smarthome Zwischenstecker außen`_
+* `Magenta SmartHome LED-Lampe E27 Warmweiß`
+* `Magenta SmartHome Zwischenstecker innen`
+* `Magenta Smarthome Tür-/Fensterkontakt magnetisch`
fritzhome CLI tool
------------------
@@ -118,3 +120,4 @@ References
.. _FRITZ!Box 6490 Cable: https://avm.de/produkte/fritzbox/fritzbox-6490-cable/
.. _Magenta Smarthome Tür-/Fensterkontakt optisch: https://www.smarthome.de/geraete/smarthome-tuer-fensterkontakt-optisch-weiss
.. _RADEMACHER RolloTron DECT 1213: https://www.rademacher.de/shop/rollladen-sonnenschutz/elektrischer-gurtwickler/rollotron-dect-1213
+.. _Magenta Smarthome Zwischenstecker außen: https://www.smarthome.de/geraete/smarthome-zwischenstecker-aussen-schwarz
\ No newline at end of file
diff --git a/pyfritzhome/cli.py b/pyfritzhome/cli.py
index 59628ee..81e6bb7 100644
--- a/pyfritzhome/cli.py
+++ b/pyfritzhome/cli.py
@@ -37,7 +37,7 @@ def list_all(fritz, args):
if device.has_switch:
print(" Switch:")
print(" switch_state=%s" % device.switch_state)
- if device.has_switch:
+ if device.has_powermeter:
print(" Powermeter:")
print(" power=%s" % device.power)
print(" energy=%s" % device.energy)
@@ -63,9 +63,11 @@ def list_all(fritz, args):
if device.has_lightbulb:
print(" Light bulb:")
print(" state=%s" % ("Off" if device.state == 0 else "On"))
- print(" level=%s" % device.level)
- print(" hue=%s" % device.hue)
- print(" saturation=%s" % device.saturation)
+ if device.has_level:
+ print(" level=%s" % device.level)
+ if device.has_color:
+ print(" hue=%s" % device.hue)
+ print(" saturation=%s" % device.saturation)
if device.has_blind:
print(" Blind:")
print(" level=%s" % device.level)
diff --git a/pyfritzhome/devicetypes/fritzhomedevicefeatures.py b/pyfritzhome/devicetypes/fritzhomedevicefeatures.py
index 8b0a0f4..cfc1e30 100644
--- a/pyfritzhome/devicetypes/fritzhomedevicefeatures.py
+++ b/pyfritzhome/devicetypes/fritzhomedevicefeatures.py
@@ -5,6 +5,7 @@
class FritzhomeDeviceFeatures(IntFlag):
"""The feature list class."""
+ LIGHTBULB = 0x0004
ALARM = 0x0010
UNKNOWN = 0x0020
BUTTON = 0x0020
@@ -16,6 +17,6 @@ class FritzhomeDeviceFeatures(IntFlag):
MICROPHONE = 0x0800
HANFUN = 0x2000
SWITCHABLE = 0x8000
- DIMMABLE = 0x10000
- LIGHTBULB = 0x20000
+ LEVEL = 0x10000
+ COLOR = 0x20000
BLIND = 0x40000
diff --git a/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py b/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py
index 8bccbd9..432df24 100644
--- a/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py
+++ b/pyfritzhome/devicetypes/fritzhomedevicelightbulb.py
@@ -36,6 +36,16 @@ def has_lightbulb(self):
"""Check if the device has LightBulb function."""
return self._has_feature(FritzhomeDeviceFeatures.LIGHTBULB)
+ @property
+ def has_level(self):
+ """Check if the device has LightBulb function."""
+ return self._has_feature(FritzhomeDeviceFeatures.LEVEL)
+
+ @property
+ def has_color(self):
+ """Check if the device has LightBulb function."""
+ return self._has_feature(FritzhomeDeviceFeatures.COLOR)
+
def _update_lightbulb_from_node(self, node):
state_element = node.find("simpleonoff")
try:
@@ -44,54 +54,56 @@ def _update_lightbulb_from_node(self, node):
except ValueError:
pass
- level_element = node.find("levelcontrol")
- try:
- self.level = self.get_node_value_as_int(level_element, "level")
-
- self.level_percentage = int(self.level / 2.55)
- except ValueError:
- pass
-
- colorcontrol_element = node.find("colorcontrol")
- try:
- self.color_mode = colorcontrol_element.attrib.get("current_mode")
-
- self.supported_color_mode = colorcontrol_element.attrib.get(
- "supported_modes"
- )
-
- except ValueError:
- pass
-
- try:
- self.hue = self.get_node_value_as_int(colorcontrol_element, "hue")
-
- self.saturation = self.get_node_value_as_int(
- colorcontrol_element, "saturation"
- )
-
- self.unmapped_hue = self.get_node_value_as_int(
- colorcontrol_element, "unmapped_hue"
- )
-
- self.unmapped_saturation = self.get_node_value_as_int(
- colorcontrol_element, "unmapped_saturation"
- )
- except ValueError:
- # reset values after color mode changed
- self.hue = None
- self.saturation = None
- self.unmapped_hue = None
- self.unmapped_saturation = None
-
- try:
- self.color_temp = self.get_node_value_as_int(
- colorcontrol_element, "temperature"
- )
-
- except ValueError:
- # reset values after color mode changed
- self.color_temp = None
+ if self.has_level:
+ level_element = node.find("levelcontrol")
+ try:
+ self.level = self.get_node_value_as_int(level_element, "level")
+
+ self.level_percentage = int(self.level / 2.55)
+ except ValueError:
+ pass
+
+ if self.has_color:
+ colorcontrol_element = node.find("colorcontrol")
+ try:
+ self.color_mode = colorcontrol_element.attrib.get("current_mode")
+
+ self.supported_color_mode = colorcontrol_element.attrib.get(
+ "supported_modes"
+ )
+
+ except ValueError:
+ pass
+
+ try:
+ self.hue = self.get_node_value_as_int(colorcontrol_element, "hue")
+
+ self.saturation = self.get_node_value_as_int(
+ colorcontrol_element, "saturation"
+ )
+
+ self.unmapped_hue = self.get_node_value_as_int(
+ colorcontrol_element, "unmapped_hue"
+ )
+
+ self.unmapped_saturation = self.get_node_value_as_int(
+ colorcontrol_element, "unmapped_saturation"
+ )
+ except ValueError:
+ # reset values after color mode changed
+ self.hue = None
+ self.saturation = None
+ self.unmapped_hue = None
+ self.unmapped_saturation = None
+
+ try:
+ self.color_temp = self.get_node_value_as_int(
+ colorcontrol_element, "temperature"
+ )
+
+ except ValueError:
+ # reset values after color mode changed
+ self.color_temp = None
def set_state_off(self):
"""Switch light bulb off."""
@@ -109,29 +121,40 @@ def set_state_toggle(self):
self._fritz.set_state_toggle(self.ain)
def set_level(self, level):
- """Set HSV color."""
- self._fritz.set_level(self.ain, level)
+ """Set level."""
+ if self.has_level:
+ self._fritz.set_level(self.ain, level)
def set_level_percentage(self, level):
"""Set HSV color in percent."""
- self._fritz.set_level_percentage(self.ain, level)
+ if self.has_level:
+ self._fritz.set_level_percentage(self.ain, level)
def get_colors(self):
"""Get the supported colors."""
- return self._fritz.get_colors(self.ain)
+ if self.has_color:
+ return self._fritz.get_colors(self.ain)
+ else:
+ return {}
def set_color(self, hsv, duration=0):
"""Set HSV color."""
- self._fritz.set_color(self.ain, hsv, duration, True)
+ if self.has_color:
+ self._fritz.set_color(self.ain, hsv, duration, True)
def set_unmapped_color(self, hsv, duration=0):
"""Set unmapped HSV color (Free color selection)."""
- self._fritz.set_color(self.ain, hsv, duration, False)
+ if self.has_color:
+ self._fritz.set_color(self.ain, hsv, duration, False)
def get_color_temps(self):
"""Get the supported color temperatures energy."""
- return self._fritz.get_color_temps(self.ain)
+ if self.has_color:
+ return self._fritz.get_color_temps(self.ain)
+ else:
+ return []
def set_color_temp(self, temperature, duration=0):
"""Set white color temperature."""
- self._fritz.set_color_temp(self.ain, temperature, duration)
+ if self.has_color:
+ self._fritz.set_color_temp(self.ain, temperature, duration)
diff --git a/pyfritzhome/devicetypes/fritzhomedeviceswitch.py b/pyfritzhome/devicetypes/fritzhomedeviceswitch.py
index 66c4165..17f015c 100644
--- a/pyfritzhome/devicetypes/fritzhomedeviceswitch.py
+++ b/pyfritzhome/devicetypes/fritzhomedeviceswitch.py
@@ -28,25 +28,39 @@ def _update_from_node(self, node):
@property
def has_switch(self):
"""Check if the device has switch function."""
- return self._has_feature(FritzhomeDeviceFeatures.SWITCH)
+ if self._has_feature(FritzhomeDeviceFeatures.SWITCH):
+ # for AVM plugs like FRITZ!DECT 200 and FRITZ!DECT 210
+ return True
+ if (self._has_feature(FritzhomeDeviceFeatures.SWITCHABLE)
+ and not self._has_feature(FritzhomeDeviceFeatures.LIGHTBULB)):
+ # for HAN-FUN plugs
+ return True
+ return False
def _update_switch_from_node(self, node):
- val = node.find("switch")
- try:
- self.switch_state = self.get_node_value_as_int_as_bool(val, "state")
- except Exception:
- self.switch_state = None
- self.switch_mode = self.get_node_value(val, "mode")
- try:
- self.lock = self.get_node_value_as_int_as_bool(val, "lock")
- except Exception:
- self.lock = None
+ if self._has_feature(FritzhomeDeviceFeatures.SWITCH):
+ val = node.find("switch")
+ try:
+ self.switch_state = self.get_node_value_as_int_as_bool(val, "state")
+ except Exception:
+ self.switch_state = None
+ self.switch_mode = self.get_node_value(val, "mode")
+ try:
+ self.lock = self.get_node_value_as_int_as_bool(val, "lock")
+ except Exception:
+ self.lock = None
- # optional value
- try:
- self.device_lock = self.get_node_value_as_int_as_bool(val, "devicelock")
- except Exception:
- pass
+ # optional value
+ try:
+ self.device_lock = self.get_node_value_as_int_as_bool(val, "devicelock")
+ except Exception:
+ pass
+ else:
+ val = node.find("simpleonoff")
+ try:
+ self.switch_state = self.get_node_value_as_int_as_bool(val, "state")
+ except Exception:
+ self.switch_state = None
def get_switch_state(self):
"""Get the switch state."""
diff --git a/tests/responses/lightbulb/device_Telekom_Magenta_NonColorBulb.xml b/tests/responses/lightbulb/device_Telekom_Magenta_NonColorBulb.xml
new file mode 100644
index 0000000..a53df92
--- /dev/null
+++ b/tests/responses/lightbulb/device_Telekom_Magenta_NonColorBulb.xml
@@ -0,0 +1,25 @@
+
+
+
+ 1
+ 0
+ Telekom Lampe
+
+
+ 1
+ 0
+ Telekom White Dimmable Bulb
+
+ 1
+
+
+ 255
+ 100
+
+
+ 401
+ 265
+ 512,513
+
+
+
diff --git a/tests/responses/switch/device_list.xml b/tests/responses/switch/device_list.xml
index 300acb1..786522d 100644
--- a/tests/responses/switch/device_list.xml
+++ b/tests/responses/switch/device_list.xml
@@ -18,4 +18,22 @@
0
+
+ 1
+ 0
+ Telekom Steckdose
+
+
+ 1
+ 0
+ Telekom Steckdose
+
+ 1
+
+
+ 402
+ 262
+ 512
+
+
\ No newline at end of file
diff --git a/tests/test_fritzhomedevicelightbulb.py b/tests/test_fritzhomedevicelightbulb.py
index 64b9dc2..ff46dfc 100644
--- a/tests/test_fritzhomedevicelightbulb.py
+++ b/tests/test_fritzhomedevicelightbulb.py
@@ -30,6 +30,8 @@ def test_device_init(self):
# Get sub-device
device = self.fritz.get_device_by_ain("12345-1")
assert device.has_lightbulb
+ assert device.has_level
+ assert device.has_color
assert device.state # Lightbulb is switched on
assert device.color_mode == "1"
assert device.supported_color_mode == "5"
@@ -38,6 +40,25 @@ def test_device_init(self):
assert device.color_temp is None
assert device.name == "FRITZ!DECT 500 Büro"
+ def test_device_init_non_color_bulb(self):
+ self.mock.side_effect = [
+ Helper.response("lightbulb/device_Telekom_Magenta_NonColorBulb")
+ ]
+
+ self.fritz.update_devices()
+ device = self.fritz.get_device_by_ain("12701 0072784")
+
+ assert device.ain == "12701 0072784"
+ assert device.fw_version == "34.09.15.16.018"
+ assert device.present # Lightbulb has power and is connected
+
+ # Get sub-device
+ device = self.fritz.get_device_by_ain("12701 0072784-1")
+ assert device.has_lightbulb
+ assert device.has_level
+ assert device.state # Lightbulb is switched on
+ assert device.name == "Telekom White Dimmable Bulb"
+
def test_device_init_color_temp_mode(self):
self.mock.side_effect = [
Helper.response("lightbulb/device_FritzDECT500_34_12_16_color_temp_mode")