def _try_connect(self): """Try to connect and check auth.""" fritzbox = Fritzhome(host=self._host, user=self._username, password=self._password) try: fritzbox.login() fritzbox.logout() return RESULT_SUCCESS except OSError: return RESULT_NOT_FOUND except LoginError: return RESULT_AUTH_FAILED
def _try_connect(self): """Try to connect and check auth.""" fritzbox = Fritzhome( host=self._host, user=self._username, password=self._password ) try: fritzbox.login() fritzbox.get_device_elements() fritzbox.logout() return RESULT_SUCCESS except LoginError: return RESULT_INVALID_AUTH except HTTPError: return RESULT_NOT_SUPPORTED except OSError: return RESULT_NO_DEVICES_FOUND
def setup(hass, config): """Set up the fritzbox component.""" from pyfritzhome import Fritzhome, LoginError fritz_list = [] if CONF_DEVICES in config[DOMAIN] and config[DOMAIN].get(CONF_DEVICES): configured_devices = config[DOMAIN].get(CONF_DEVICES) for device in configured_devices: try: host = device['host'] username = device['username'] password = device['password'] fritzbox = Fritzhome(host=host, user=username, password=password) fritzbox.login() fritz_list.append(fritzbox) _LOGGER.info("Connected to device %s", device) except LoginError: _LOGGER.warning("Login to Fritz!Box %s as %s failed", host, username) continue except KeyError: _LOGGER.warning("Configuration error") continue hass.data[DOMAIN] = fritz_list def logout_fritzboxes(event): """Close all connections to the fritzboxes.""" for fritz in fritz_list: fritz.logout() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, logout_fritzboxes) for domain in SUPPORTED_DOMAINS: discovery.load_platform(hass, domain, DOMAIN, {}, config) _LOGGER.info('Connected to fritzbox') return True
def setup(hass, config): """Set up the fritzbox component.""" from pyfritzhome import Fritzhome, LoginError fritz_list = [] configured_devices = config[DOMAIN].get(CONF_DEVICES) for device in configured_devices: host = device.get(CONF_HOST) username = device.get(CONF_USERNAME) password = device.get(CONF_PASSWORD) fritzbox = Fritzhome(host=host, user=username, password=password) try: fritzbox.login() _LOGGER.info("Connected to device %s", device) except LoginError: _LOGGER.warning("Login to Fritz!Box %s as %s failed", host, username) continue fritz_list.append(fritzbox) if not fritz_list: _LOGGER.info("No fritzboxes configured") return False hass.data[DOMAIN] = fritz_list def logout_fritzboxes(event): """Close all connections to the fritzboxes.""" for fritz in fritz_list: fritz.logout() hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, logout_fritzboxes) for domain in SUPPORTED_DOMAINS: discovery.load_platform(hass, domain, DOMAIN, {}, config) return True
def main(args=None): """The main function.""" parser = argparse.ArgumentParser( description='Fritz!Box Smarthome CLI tool.') parser.add_argument('-v', action='store_true', dest='verbose', help='be more verbose') parser.add_argument('-f', '--fritzbox', type=str, dest='host', help='Fritz!Box IP address', default='fritz.box') parser.add_argument('-u', '--user', type=str, dest='user', help='Username') parser.add_argument('-p', '--password', type=str, dest='password', help='Username') parser.add_argument('-a', '--ain', type=str, dest='ain', help='Actor Identification', default=None) parser.add_argument('-V', '--version', action='version', version='{version}'.format(version=__version__), help='Print version') _sub = parser.add_subparsers(title='Commands') # list all devices subparser = _sub.add_parser('list', help='List all available devices') subparser.set_defaults(func=list_all) # device subparser = _sub.add_parser('device', help='Device/Actor commands') _sub_switch = subparser.add_subparsers() # device name subparser = _sub_switch.add_parser('name', help='get the device name') subparser.add_argument('ain', type=str, metavar="AIN", help='Actor Identification') subparser.set_defaults(func=device_name) # device presence subparser = _sub_switch.add_parser('present', help='get the device presence') subparser.add_argument('ain', type=str, metavar="AIN", help='Actor Identification') subparser.set_defaults(func=device_presence) # device stats subparser = _sub_switch.add_parser('stats', help='get the device statistic') subparser.add_argument('ain', type=str, metavar="AIN", help='Actor Identification') subparser.set_defaults(func=device_statistic) # switch subparser = _sub.add_parser('switch', help='Switch commands') _sub_switch = subparser.add_subparsers() # switch get subparser = _sub_switch.add_parser('get', help='get state') subparser.add_argument('ain', type=str, metavar="AIN", help='Actor Identification') subparser.set_defaults(func=switch_get) # switch on subparser = _sub_switch.add_parser('on', help='set on state') subparser.add_argument('ain', type=str, metavar="AIN", help='Actor Identification') subparser.set_defaults(func=switch_on) # switch off subparser = _sub_switch.add_parser('off', help='set off state') subparser.add_argument('ain', type=str, metavar="AIN", help='Actor Identification') subparser.set_defaults(func=switch_off) # switch toggle subparser = _sub_switch.add_parser('toggle', help='set off state') subparser.add_argument('ain', type=str, metavar="AIN", help='Actor Identification') subparser.set_defaults(func=switch_toggle) args = parser.parse_args(args) logging.basicConfig() if args.verbose: logging.getLogger('pyfritzhome').setLevel(logging.DEBUG) fritzbox = None try: fritzbox = Fritzhome(host=args.host, user=args.user, password=args.password) fritzbox.login() args.func(fritzbox, args) finally: if fritzbox is not None: fritzbox.logout()
class AVM_smarthome(SmartPlugin): """ Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the items """ PLUGIN_VERSION = '1.0.A' # (must match the version specified in plugin.yaml) def __init__(self, sh): """ Initalizes the plugin. If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for a reference to the sh object any more. Plugins have to use the new way of getting parameter values: use the SmartPlugin method get_parameter_value(parameter_name). Anywhere within the Plugin you can get the configured (and checked) value for a parameter by calling self.get_parameter_value(parameter_name). It returns the value in the datatype that is defined in the metadata. """ # Call init code of parent class (SmartPlugin) super().__init__() from bin.smarthome import VERSION if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': self.logger = logging.getLogger(__name__) # get the parameters for the plugin (as defined in metadata plugin.yaml): self._cycle = self.get_parameter_value( 'cycle' ) # the frequency in seconds how often the query shoud be done self.host = self.get_parameter_value( 'host') # IP Adress of the fritzbox self.user = self.get_parameter_value('username') # Username self.password = self.get_parameter_value('password') # Password # Initialization code goes here self.fritzbox = None self.alive = False self._ain_items = [ ] # Liste aller Items, die die AIN als Datentyp haben self._device_dict = { } # Dict, in das die Daten der AVM Abfrage geschrieben werden self.avm_smarthome_items = [] # to hold items for web interface self.avm_smarthome_devices = { } # to hold device information for web interface self.avm_smarthome_meta = { } # to hold meta information for web interface # On initialization error use: # self._init_complete = False # return # if plugin should start even without web interface self.init_webinterface() # if plugin should not start without web interface # if not self.init_webinterface(): # self._init_complete = False self.connect() return def run(self): """ Run method for the plugin """ self.logger.debug("Run method called") self.scheduler_add('poll_device', self.poll_device, cycle=self._cycle) self.alive = True # discover all connected AVM smarthome devices self.poll_device def stop(self): """ Stop method for the plugin """ self.logger.debug("Stop method called") self.disconnect() self.alive = False def connect(self): """ Connects to the AVM Fritzbox """ try: self.fritzbox = Fritzhome(host=self.host, user=self.user, password=self.password) self.fritzbox.login() self.logger.debug('Login to Fritz!Box {} as {} successful.'.format( self.host, self.user)) except LoginError: self.logger.debug('Login to Fritz!Box {} as {} failed.'.format( self.host, self.user)) def disconnect(self): """ Disconnects from the AVM Fritzbox """ if self.fritzbox is not None: self.fritzbox.logout() self.logger.debug('Logout successful') def reconnect(self): """ Reconnects to the call monitor of the AVM device """ self.disconnect() self.connect() def parse_item(self, item): """ Default plugin parse_item method. Is called when the plugin is initialized. The plugin can, corresponding to its attribute keywords, decide what to do with the item in future, like adding it to an internal array for future reference :param item: The item to process. :return: If the plugin needs to be informed of an items change you should return a call back function like the function update_item down below. An example when this is needed is the knx plugin where parse_item returns the update_item function when the attribute knx_send is found. This means that when the items value is about to be updated, the call back function is called with the item, caller, source and dest as arguments and in case of the knx plugin the value can be sent to the knx with a knx write function within the knx plugin. """ if self.has_iattr(item.conf, 'avm_smarthome_data') or self.has_iattr( item.conf, 'avm_ain'): self.logger.debug(f"parsing item: {item.id()}") datatype = self.get_iattr_value(item.conf, 'avm_smarthome_data') ain = self.get_iattr_value(item.conf, 'avm_ain') if ain is not None: self.logger.debug( f" Item {item.id()} with avm_ain attribut found; append to list" ) self._ain_items.append(item) else: parent_item = item.return_parent() ain = self.get_iattr_value(parent_item.conf, 'avm_ain') if datatype is not None: self.logger.debug( f" Item {item.id()} with avm_smarthome_data attribut found; append to list" ) self.avm_smarthome_items.append(item) if not self.avm_smarthome_devices.get(ain): self.avm_smarthome_devices[ain] = {} self.avm_smarthome_devices[ain]['connected_to_item'] = False # self.avm_smarthome_devices[ain]['connected_items'] = {} self.avm_smarthome_devices[ain]['switch'] = {} self.avm_smarthome_devices[ain]['temperature_sensor'] = {} self.avm_smarthome_devices[ain]['thermostat'] = {} self.avm_smarthome_devices[ain]['alarm'] = {} self.logger.debug( f"Item parsed connected with AIN: {ain} and datatype: {datatype}" ) self.avm_smarthome_devices[ain]['connected_to_item'] = True # if datatype is not None: # self.avm_smarthome_devices[ain]['connected_items']['item_'+datatype] = item # self.logger.debug(f"--parse_item-- avm_smarthome_devices: {self.avm_smarthome_devices}") # self.logger.debug(f"--parse_item-- _ain_items: {self._ain_items}") return self.update_item def parse_logic(self, logic): """ Default plugin parse_logic method """ if 'xxx' in logic.conf: # self.function(logic['name']) pass def update_item(self, item, caller=None, source=None, dest=None): """ Item has been updated This method is called, if the value of an item has been updated by SmartHomeNG. It should write the changed value out to the device (hardware/interface) that is managed by this plugin. :param item: item to be updated towards the plugin :param caller: if given it represents the callers name :param source: if given it represents the source :param dest: if given it represents the dest """ if self.alive and caller != self.get_shortname(): # code to execute if the plugin is not stopped # and only, if the item has not been changed by this this plugin: self.logger.info( "Update item: {}, item has been changed outside this plugin". format(item.id())) if self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'set_temperature': self.logger.debug( "update_item was called with item '{}' from caller '{}', source '{}' and dest '{}'" .format(item, caller, source, dest)) cmd_temperature = float(item()) self.logger.debug("cmd_temp is: {0}".format(cmd_temperature)) parentItem = item.return_parent() ainDevice = '0' if isinstance(parentItem.conf['avm_ain'], str): ainDevice = parentItem.conf['avm_ain'] else: self.logger.error('device ain is not a string value') self.logger.info("Target ain is {0}".format(ainDevice)) self.fritzbox.set_target_temperature(ainDevice, cmd_temperature) if self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'set_switch_state': self.logger.debug( "update_item was called with item '{}' from caller '{}', source '{}' and dest '{}'" .format(item, caller, source, dest)) state = bool(item()) parentItem = item.return_parent() ainDevice = '0' if isinstance(parentItem.conf['avm_ain'], str): ainDevice = parentItem.conf['avm_ain'] else: self.logger.error('device ain is not a string value') self.logger.info("Target ain is {0}".format(ainDevice)) if state is True: self.fritzbox.set_switch_state_on(ainDevice) else: self.fritzbox.set_switch_state_off(ainDevice) if self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'set_switch_state_toggle': self.logger.debug( "update_item was called with item '{}' from caller '{}', source '{}' and dest '{}'" .format(item, caller, source, dest)) state = bool(item()) parentItem = item.return_parent() ainDevice = '0' if isinstance(parentItem.conf['avm_ain'], str): ainDevice = parentItem.conf['avm_ain'] else: self.logger.error('device ain is not a string value') self.logger.info("Target ain is {0}".format(ainDevice)) self.fritzbox.set_switch_state_toggle(ainDevice) pass def poll_device(self): """ This method gets called by scheduler and queries all data """ self.logger.debug('Starting update loop for instance {}.'.format( self.get_instance_name())) # Request AVM Data self._device_dict = self.fritzbox.get_devices_as_dict() # Update WebIF Dict for ain in self._device_dict: if not self.avm_smarthome_devices.get(ain): self.avm_smarthome_devices[ain] = {} self.avm_smarthome_devices[ain]['connected_to_item'] = False # self.avm_smarthome_devices[ain]['connected_items'] = {} self.avm_smarthome_devices[ain]['switch'] = {} self.avm_smarthome_devices[ain]['temperature_sensor'] = {} self.avm_smarthome_devices[ain]['thermostat'] = {} self.avm_smarthome_devices[ain]['alarm'] = {} self.avm_smarthome_devices[ain]['online'] = bool( self._device_dict[ain].present) self.avm_smarthome_devices[ain]['name'] = self._device_dict[ ain].name self.avm_smarthome_devices[ain]['productname'] = self._device_dict[ ain].productname self.avm_smarthome_devices[ain][ 'manufacturer'] = self._device_dict[ain].manufacturer self.avm_smarthome_devices[ain]['fw_version'] = self._device_dict[ ain].fw_version self.avm_smarthome_devices[ain]['lock'] = bool( self._device_dict[ain].lock) self.avm_smarthome_devices[ain]['device_lock'] = bool( self._device_dict[ain].device_lock) self.avm_smarthome_devices[ain]['has_switch'] = bool( self._device_dict[ain].has_switch) self.avm_smarthome_devices[ain]['has_temperature_sensor'] = bool( self._device_dict[ain].has_temperature_sensor) self.avm_smarthome_devices[ain]['has_thermostat'] = bool( self._device_dict[ain].has_thermostat) self.avm_smarthome_devices[ain]['has_alarm'] = bool( self._device_dict[ain].has_alarm) if self._device_dict[ain].has_thermostat: self.avm_smarthome_devices[ain]['thermostat'][ 'actual_temperature'] = self._device_dict[ ain].actual_temperature self.avm_smarthome_devices[ain]['thermostat'][ 'target_temperature'] = self._device_dict[ ain].target_temperature self.avm_smarthome_devices[ain]['thermostat'][ 'comfort_temperature'] = self._device_dict[ ain].comfort_temperature self.avm_smarthome_devices[ain]['thermostat'][ 'eco_temperature'] = self._device_dict[ain].eco_temperature self.avm_smarthome_devices[ain]['thermostat'][ 'battery_low'] = bool(self._device_dict[ain].battery_low) self.avm_smarthome_devices[ain]['thermostat'][ 'battery_level'] = self._device_dict[ain].battery_level self.avm_smarthome_devices[ain]['thermostat'][ 'window_open'] = bool(self._device_dict[ain].window_open) self.avm_smarthome_devices[ain]['thermostat'][ 'summer_active'] = bool( self._device_dict[ain].summer_active) self.avm_smarthome_devices[ain]['thermostat'][ 'holiday_active'] = bool( self._device_dict[ain].holiday_active) if self._device_dict[ain].has_switch: self.avm_smarthome_devices[ain]['switch'][ 'switch_state'] = bool(self._device_dict[ain].switch_state) self.avm_smarthome_devices[ain]['switch'][ 'power'] = self._device_dict[ain].power self.avm_smarthome_devices[ain]['switch'][ 'energy'] = self._device_dict[ain].energy self.avm_smarthome_devices[ain]['switch'][ 'voltage'] = self._device_dict[ain].voltage if self._device_dict[ain].has_temperature_sensor: self.avm_smarthome_devices[ain]['temperature_sensor'][ 'temperature'] = self._device_dict[ain].temperature self.avm_smarthome_devices[ain]['temperature_sensor'][ 'offset'] = self._device_dict[ain].offset if self._device_dict[ain].has_alarm: self.avm_smarthome_devices[ain]['alarm']['alert_state'] = bool( self._device_dict[ain].alert_state) self.logger.debug( f"Discovered avm smarthome devices and data: {self.avm_smarthome_devices}" ) # update tasmota_meta auf Basis von tasmota_devices self.avm_smarthome_meta = {} for ain in self.avm_smarthome_devices: if self.avm_smarthome_devices[ain]['has_switch']: self.avm_smarthome_meta['switch'] = True if self.avm_smarthome_devices[ain]['has_thermostat']: self.avm_smarthome_meta['thermostat'] = True if self.avm_smarthome_devices[ain]['has_temperature_sensor']: self.avm_smarthome_meta['temperature_sensor'] = True if self.avm_smarthome_devices[ain]['has_alarm']: self.avm_smarthome_meta['alarm'] = True # update items for item in self._ain_items: if self.has_iattr(item.conf, 'avm_ain'): item_ain = self.get_iattr_value(item.conf, 'avm_ain') self.logger.debug( f" Item {item.id()} with defined avm_ain attribut {item_ain}" ) device = self._device_dict[item_ain] if self.has_iattr(item.conf, 'avm_smarthome_data'): self._set_item_value(item, device) else: self.logger.debug( f" No attribut 'avm_smarthome_data' found on item {item.id()}; checking child items" ) for child in item.return_children(): self.logger.debug( f" Child item {child.id()} processed and checked for attribut 'avm_smarthome_data' " ) if self.has_iattr(child.conf, 'avm_smarthome_data'): self._set_item_value(child, device) pass def _set_item_value(self, item, device): if self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'name': item(device.name, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'ain': item(device.ain, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'identifier': item(device.identifier, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'productname': item(device.productname, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'manufacturer': item(device.manufacturer, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'firmware_version': item(device.fw_version, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'present': item(device.present, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'lock': item(device.lock, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'device_lock': item(device.device_lock, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'has_switch': item(device.has_switch, self.get_shortname()) elif self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'has_temperature_sensor': item(device.has_temperature_sensor, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'has_thermostat': item(device.has_thermostat, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'has_alarm': item(device.has_alarm, self.get_shortname()) if device.has_switch: if self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'switch_state': item(device.switch_state, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'power': item(device.power, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'energy': item(device.energy, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'voltage': item(device.voltage, self.get_shortname()) if device.has_temperature_sensor: if self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'temperature': item(device.temperature, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'offset': item(device.offset, self.get_shortname()) if device.has_thermostat: if self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'actual_temperature': item(device.actual_temperature, self.get_shortname()) elif self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'target_temperature': item(device.target_temperature, self.get_shortname()) elif self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'comfort_temperature': item(device.comfort_temperature, self.get_shortname()) elif self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'eco_temperature': item(device.eco_temperature, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'battery_low': item(device.battery_low, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'battery_level': item(device.battery_level, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'window_open': item(device.window_open, self.get_shortname()) elif self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'summer_active': item(device.summer_active, self.get_shortname()) elif self.get_iattr_value( item.conf, 'avm_smarthome_data') == 'holiday_active': item(device.holiday_active, self.get_shortname()) if device.has_alarm: if self.get_iattr_value(item.conf, 'avm_smarthome_data') == 'alert_state': item(device.alert_state, self.get_shortname()) def init_webinterface(self): """" Initialize the web interface for this plugin This method is only needed if the plugin is implementing a web interface """ try: self.mod_http = Modules.get_instance().get_module( 'http' ) # try/except to handle running in a core version that does not support modules except: self.mod_http = None if self.mod_http == None: self.logger.error("Not initializing the web interface") return False import sys if not "SmartPluginWebIf" in list( sys.modules['lib.model.smartplugin'].__dict__): self.logger.warning( "Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface" ) return False # set application configuration for cherrypy webif_dir = self.path_join(self.get_plugin_dir(), 'webif') config = { '/': { 'tools.staticdir.root': webif_dir, }, '/static': { 'tools.staticdir.on': True, 'tools.staticdir.dir': 'static' } } # Register the web interface as a cherrypy app self.mod_http.register_webif(WebInterface(webif_dir, self), self.get_shortname(), config, self.get_classname(), self.get_instance_name(), description='') return True
class TestFritzhome(object): def setup(self): self.mock = MagicMock() self.fritz = Fritzhome("10.0.0.1", "user", "pass") self.fritz._request = self.mock @raises(LoginError) def test_login_fail(self): self.mock.side_effect = [ response("login_rsp_without_valid_sid"), response("login_rsp_without_valid_sid"), ] self.fritz.login() def test_login(self): self.mock.side_effect = [ response("login_rsp_without_valid_sid"), response("login_rsp_with_valid_sid"), ] self.fritz.login() def test_logout(self): self.fritz.logout() self.fritz._request.assert_called_with( "http://10.0.0.1/login_sid.lua", {"sid": None, "security:command/logout": "1"}, ) def test_aha_request(self): self.fritz._aha_request(cmd="testcmd") self.fritz._request.assert_called_with( "http://10.0.0.1/webservices/homeautoswitch.lua", {"sid": None, "switchcmd": "testcmd"}, ) self.fritz._aha_request(cmd="testcmd", ain="1") self.fritz._request.assert_called_with( "http://10.0.0.1/webservices/homeautoswitch.lua", {"sid": None, "switchcmd": "testcmd", "ain": "1"}, ) self.fritz._aha_request(cmd="testcmd", ain="1", param={"a": "1", "b": "2"}) self.fritz._request.assert_called_with( "http://10.0.0.1/webservices/homeautoswitch.lua", { "sid": None, "switchcmd": "testcmd", "ain": "1", "param": {"a": "1", "b": "2"}, }, ) @raises(InvalidError) def test_aha_request_invalid(self): self.mock.side_effect = [ "inval", ] self.fritz._aha_request(cmd="estcmd") def test_get_device_element(self): self.mock.side_effect = [ response("device_list"), response("device_list"), response("device_list"), ] element = self.fritz.get_device_element("08761 0000434") eq_(element.attrib["identifier"], "08761 0000434") eq_(element.attrib["fwversion"], "03.33") element = self.fritz.get_device_element("08761 1048079") eq_(element.attrib["identifier"], "08761 1048079") eq_(element.attrib["fwversion"], "03.44") element = self.fritz.get_device_element("unknown") eq_(element, None) def test_get_device_by_ain(self): self.mock.side_effect = [ response("device_list"), response("device_list"), ] device = self.fritz.get_device_by_ain("08761 0000434") eq_(device.ain, "08761 0000434") def test_aha_get_devices(self): self.mock.side_effect = [ response("device_list"), ] devices = self.fritz.get_devices() eq_(devices[0].name, "Steckdose") eq_(devices[1].name, "FRITZ!DECT Rep 100 #1") def test_get_device_name(self): self.mock.side_effect = ["testname"] eq_(self.fritz.get_device_name(ain="1234"), "testname") self.fritz._request.assert_called_with( "http://10.0.0.1/webservices/homeautoswitch.lua", {"sid": None, "ain": "1234", "switchcmd": "getswitchname"}, ) def test_set_target_temperature(self): self.fritz.set_target_temperature("1", 25.5) self.fritz._request.assert_called_with( "http://10.0.0.1/webservices/homeautoswitch.lua", {"sid": None, "ain": "1", "switchcmd": "sethkrtsoll", "param": 51}, ) self.fritz.set_target_temperature("1", 0.0) self.fritz._request.assert_called_with( "http://10.0.0.1/webservices/homeautoswitch.lua", {"sid": None, "ain": "1", "switchcmd": "sethkrtsoll", "param": 253}, ) self.fritz.set_target_temperature("1", 32.0) self.fritz._request.assert_called_with( "http://10.0.0.1/webservices/homeautoswitch.lua", {"sid": None, "ain": "1", "switchcmd": "sethkrtsoll", "param": 254}, ) def test_get_alert_state(self): self.mock.side_effect = [ response("device_list"), ] eq_(self.fritz.get_alert_state("05333 0077045-1"), True)
class TestFritzhome(object): def setup(self): self.mock = MagicMock() self.fritz = Fritzhome('10.0.0.1', 'user', 'pass') self.fritz._request = self.mock @raises(LoginError) def test_login_fail(self): self.mock.side_effect = [ login_rsp_without_valid_sid, login_rsp_without_valid_sid, ] self.fritz.login() def test_login(self): self.mock.side_effect = [ login_rsp_without_valid_sid, login_rsp_with_valid_sid, ] self.fritz.login() def test_logout(self): self.fritz.logout() self.fritz._request.assert_called_with( 'http://10.0.0.1/login_sid.lua', { 'sid': None, 'security:command/logout': '1' }) def test_aha_request(self): self.fritz._aha_request(cmd='testcmd') self.fritz._request.assert_called_with( 'http://10.0.0.1/webservices/homeautoswitch.lua', { 'sid': None, 'switchcmd': 'testcmd' }) self.fritz._aha_request(cmd='testcmd', ain='1') self.fritz._request.assert_called_with( 'http://10.0.0.1/webservices/homeautoswitch.lua', { 'sid': None, 'switchcmd': 'testcmd', 'ain': '1' }) self.fritz._aha_request(cmd='testcmd', ain='1', param={ 'a': '1', 'b': '2' }) self.fritz._request.assert_called_with( 'http://10.0.0.1/webservices/homeautoswitch.lua', { 'sid': None, 'switchcmd': 'testcmd', 'ain': '1', 'param': { 'a': '1', 'b': '2' } }) @raises(InvalidError) def test_aha_request_invalid(self): self.mock.side_effect = [ 'inval', ] self.fritz._aha_request(cmd='estcmd') def test_get_device_element(self): self.mock.side_effect = [ device_list_xml, device_list_xml, device_list_xml, ] element = self.fritz.get_device_element('08761 0000434') eq_(element.getAttribute('identifier'), '08761 0000434') eq_(element.getAttribute('fwversion'), '03.33') element = self.fritz.get_device_element('08761 1048079') eq_(element.getAttribute('identifier'), '08761 1048079') eq_(element.getAttribute('fwversion'), '03.44') element = self.fritz.get_device_element('unknown') eq_(element, None) def test_get_device_by_ain(self): self.mock.side_effect = [ device_list_xml, device_list_xml, ] device = self.fritz.get_device_by_ain('08761 0000434') eq_(device.ain, '08761 0000434') def test_aha_get_devices(self): self.mock.side_effect = [ device_list_xml, ] devices = self.fritz.get_devices() eq_(devices[0].name, 'Steckdose') eq_(devices[1].name, 'FRITZ!DECT Rep 100 #1') def test_get_device_name(self): self.mock.side_effect = ['testname'] eq_(self.fritz.get_device_name(ain='1234'), 'testname') self.fritz._request.assert_called_with( 'http://10.0.0.1/webservices/homeautoswitch.lua', { 'sid': None, 'ain': '1234', 'switchcmd': 'getswitchname' }) def test_set_target_temperature(self): self.fritz.set_target_temperature('1', 25.5) self.fritz._request.assert_called_with( 'http://10.0.0.1/webservices/homeautoswitch.lua', { 'sid': None, 'ain': '1', 'switchcmd': 'sethkrtsoll', 'param': 51 }) self.fritz.set_target_temperature('1', 0.0) self.fritz._request.assert_called_with( 'http://10.0.0.1/webservices/homeautoswitch.lua', { 'sid': None, 'ain': '1', 'switchcmd': 'sethkrtsoll', 'param': 253 }) self.fritz.set_target_temperature('1', 32.0) self.fritz._request.assert_called_with( 'http://10.0.0.1/webservices/homeautoswitch.lua', { 'sid': None, 'ain': '1', 'switchcmd': 'sethkrtsoll', 'param': 254 }) def test_get_alert_state(self): self.mock.side_effect = [ device_list_xml, ] eq_(self.fritz.get_alert_state('05333 0077045-1'), True)
def main(args=None): """The main function.""" parser = argparse.ArgumentParser(description="Fritz!Box Smarthome CLI tool.") parser.add_argument( "-v", action="store_true", dest="verbose", help="be more verbose" ) parser.add_argument( "-f", "--fritzbox", type=str, dest="host", help="Fritz!Box IP address", default="fritz.box", ) parser.add_argument("-u", "--user", type=str, dest="user", help="Username") parser.add_argument("-p", "--password", type=str, dest="password", help="Username") parser.add_argument( "-a", "--ain", type=str, dest="ain", help="Actor/Template Identification", default=None, ) parser.add_argument( "-V", "--version", action="version", version="{version}".format(version=__version__), help="Print version", ) _sub = parser.add_subparsers(title="Commands") # list all devices subparser = _sub.add_parser("list", help="List all available devices") subparser.set_defaults(func=list_all) # device subparser = _sub.add_parser("device", help="Device/Actor commands") _sub_switch = subparser.add_subparsers() # device name subparser = _sub_switch.add_parser("name", help="get the device name") subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification") subparser.set_defaults(func=device_name) # device presence subparser = _sub_switch.add_parser("present", help="get the device presence") subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification") subparser.set_defaults(func=device_presence) # device stats subparser = _sub_switch.add_parser("stats", help="get the device statistics") subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification") subparser.set_defaults(func=device_statistics) # switch subparser = _sub.add_parser("switch", help="Switch commands") _sub_switch = subparser.add_subparsers() # switch get subparser = _sub_switch.add_parser("get", help="get state") subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification") subparser.set_defaults(func=switch_get) # switch on subparser = _sub_switch.add_parser("on", help="set on state") subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification") subparser.set_defaults(func=switch_on) # switch off subparser = _sub_switch.add_parser("off", help="set off state") subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification") subparser.set_defaults(func=switch_off) # switch toggle subparser = _sub_switch.add_parser("toggle", help="set off state") subparser.add_argument("ain", type=str, metavar="AIN", help="Actor Identification") subparser.set_defaults(func=switch_toggle) # templates subparser = _sub.add_parser("template", help="Template commands") _sub_switch = subparser.add_subparsers() # list templates subparser = _sub_switch.add_parser("list", help="List all available templates") subparser.set_defaults(func=list_templates) # apply templates subparser = _sub_switch.add_parser("apply", help="Apply template") subparser.set_defaults(func=template_apply) args = parser.parse_args(args) logging.basicConfig() if args.verbose: logging.getLogger("pyfritzhome").setLevel(logging.DEBUG) fritzbox = None try: fritzbox = Fritzhome(host=args.host, user=args.user, password=args.password) fritzbox.login() args.func(fritzbox, args) finally: if fritzbox is not None: fritzbox.logout()