-
-
Save fake666/75c035c74b7be448dd9b3d1316ea6cfe to your computer and use it in GitHub Desktop.
""" | |
A homeassistant switch component to enable or disable fritz! box call deflections / call forwarding | |
tr 064 needs to be enabled, and call deflections have to be pre-defined in the box's ui. | |
removing and adding calldeflections while homeassistant is running will break this ;-) | |
""" | |
import logging | |
import voluptuous as vol | |
from homeassistant.components.switch import (SwitchEntity, PLATFORM_SCHEMA) | |
from homeassistant.const import (CONF_HOST, CONF_PORT, CONF_PASSWORD, CONF_USERNAME) | |
import homeassistant.helpers.config_validation as cv | |
REQUIREMENTS = ['fritzconnection==1.3.0'] | |
_LOGGER = logging.getLogger(__name__) | |
DEFAULT_HOST = '169.254.1.1' # IP valid for all Fritz!Box routers | |
DEFAULT_PORT = 49000 | |
ATTR_TRIGGER_NUMBER = 'trigger_number' | |
ATTR_TARGET_NUMBER = 'target_number' | |
ATTR_UID = 'uid' | |
SERVICE = 'X_AVM-DE_OnTel' | |
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ | |
vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string, | |
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, | |
vol.Required(CONF_PASSWORD): cv.string, | |
vol.Optional(CONF_USERNAME, default=''): cv.string, | |
}) | |
def setup_platform(hass, config, add_entities, discovery_info=None): | |
"""Set up Fritz!Box call deflection switch platform.""" | |
host = config.get(CONF_HOST) | |
port = config.get(CONF_PORT) | |
username = config.get(CONF_USERNAME) | |
password = config.get(CONF_PASSWORD) | |
from lxml import etree | |
import fritzconnection as fc | |
fritz_connection = None; | |
if username != '': | |
fritz_connection = fc.FritzConnection(address=host, password=password, user=username, port=port) | |
else: | |
fritz_connection = fc.FritzConnection(address=host, password=password, port=port) | |
raw_deflections = fritz_connection.call_action(SERVICE, "GetDeflections")["NewDeflectionList"]; | |
element_tree = etree.fromstring(raw_deflections); | |
switches = [] | |
for element in element_tree.findall('Item'): | |
uid = element.find('DeflectionId').text | |
enabled = int(element.find('Enable').text) | |
from_number = element.find('Number').text | |
to_number = element.find('DeflectionToNumber').text | |
# forwardings without to_number are blocked numbers | |
if to_number is None: | |
continue | |
switches.append(FritzCallDeflectSwitch(hass=hass, fritz_connection=fritz_connection, uid=uid, from_number=from_number, to_number=to_number, enabled=enabled)) | |
add_entities(switches); | |
class FritzCallDeflectSwitch(SwitchEntity): | |
"""Representation of a FRITZ! call deflection switch.""" | |
def __init__(self, hass, fritz_connection, uid, from_number, to_number, enabled): | |
"""Initialize the switch.""" | |
self._hass = hass; | |
self._fritz_connection = fritz_connection; | |
self._uid = uid; | |
self._from_number = from_number; | |
self._to_number = to_number; | |
self._enabled = enabled; | |
@property | |
def name(self): | |
"""Return the name of the FRITZ! call deflection (just the uid)""" | |
return "fritzdeflect_" + str(self._uid); | |
@property | |
def device_state_attributes(self): | |
"""Return the state attributes of the call deflection.""" | |
attrs = {} | |
attrs[ATTR_TRIGGER_NUMBER] = "{}".format(self._from_number) | |
attrs[ATTR_TARGET_NUMBER] = "{}".format(self._to_number) | |
attrs[ATTR_UID] = "{}".format(self._uid); | |
return attrs | |
@property | |
def is_on(self): | |
"""Return true if switch is on.""" | |
return self._enabled; | |
def turn_on(self, **kwargs): | |
"""Turn the switch on.""" | |
myargs = {'NewDeflectionId': self._uid, 'NewEnable': 1 } | |
self._fritz_connection.call_action(SERVICE, "SetDeflectionEnable", **myargs); | |
def turn_off(self, **kwargs): | |
"""Turn the switch off.""" | |
myargs = {'NewDeflectionId': self._uid, 'NewEnable': 0 } | |
self._fritz_connection.call_action(SERVICE, "SetDeflectionEnable", **myargs); | |
def update(self): | |
"""Get the latest data from the fritz box and update the state""" | |
kwargs = {'NewDeflectionId': self._uid } | |
try: | |
updated_dict = self._fritz_connection.call_action(SERVICE, "GetDeflection", **kwargs); | |
self._from_number = updated_dict['NewNumber']; | |
self._to_number = updated_dict['NewDeflectionToNumber']; | |
self._enabled = int(updated_dict['NewEnable']); | |
except TypeError: | |
pass | |
Is this still working?
I got the following error:
Platform error switch.fritzbox_calldeflection - Integration 'fritzbox_calldeflection' not found.
hi, the layout for custom components changed a bit a while back, insteaf of custom_components/switch it now has to be placed in
custom_components/fritzbox_calldeflection/switch.py
you may also need to create an empty __init__.py
in the same directory.
Thank you for your help. I have done this but I get the same error message.
Ok. Now I am one step closer.
I renamed folder an file and changed the configuration.yaml entry
fritzbox_calldeflection:
host: 192.168.178.1 (optional)
username: myuser (optional)
password: !secret fb_pass
But now I get the following error:
Setup failed for fritzbox_calldeflection: No setup function defined.
here's my config:
switch:
- platform: fritzbox_calldeflection
host: 192.168.178.1
password: !secret fb_password
If I change my config like yours, home assistant don‘t start anymore.
Did you have other files in /custom_components/fritzbox_calldeflection?
no, just switch.py
and the empty __init__.py
.
do any other custom components work for you? does homeassistant have write permission on this directory?
Yes i have other custom components and they are working.
The permission of the folder and files are 777.
usage: drop in custom_compoments/switch, add (in configuration.yaml):
switch:
platform: fritzbox_calldeflection
host: 192.168.178.1 (optional)
username: myuser (optional)
password: !secret fb_pass
restart HA