""" fritzinspection.py Module to inspect the FritzBox API for available services and actions. This module is part of the FritzConnection package. https://github.com/kbr/fritzconnection License: MIT (https://opensource.org/licenses/MIT) Author: Klaus Bremer """ import datetime from ..core.exceptions import FritzAuthorizationError from ..core.fritzconnection import FritzConnection from .utils import ( get_cli_arguments, get_instance, print_header, print_common_exception_message ) class FritzInspection: """ Class for cli use to inspect available services and according actions of the given device (the Fritz!Box). """ # pylint: disable=invalid-name # self.fc is ok. def __init__(self, fc): self.fc = fc def view_servicenames(self): """Send all known service names to stdout.""" print('Servicenames:') for service_name in self.fc.services: print('{:20}{}'.format('', service_name)) def view_actionnames(self, service_name, view_arguments=False): """Send all action names of the given service to stdout.""" print('\n{:<20}{}'.format('Servicename:', service_name)) print('Actionnames:') try: service = self.fc.services[service_name] except KeyError as err: print(f'Error: Invalid Servicename {err}') else: for action_name in service.actions: print('{:20}{}'.format('', action_name)) if view_arguments: action = service.actions[action_name] for argument in sorted(action.arguments.keys()): print('{:24}- {}'.format('', argument)) print() def view_actionarguments(self, service_name, action_name): """Send all action names of the given service to stdout.""" try: service = self.fc.services[service_name] except KeyError as err: print(f'Error: Invalid Servicename {err}') return try: action = service.actions[action_name] except KeyError as err: print(f'Error: Invalid Actionname {err}') return print('\n{:<20}{}'.format('Service:', service_name)) print('{:<20}{}'.format('Action:', action_name)) print('Parameters:\n') print(' {:38}{:14}{}\n'.format('Name', 'direction', 'data type')) for argument in action.arguments.values(): if argument.direction == 'in': direction = '-> in' else: direction = ' out ->' var = service.state_variables.get(argument.relatedStateVariable, '') line = f' {argument.name:38}{direction:14}{var.dataType}' print(line) def view_complete_api(self): """ Send the complete api to stdout. This can be a lengthy output that may be redirected to a file. """ print() system_info = self.fc.device_manager.system_info # some devices may return None as system_info if system_info: print( f"system : {system_info[-1]}\n" f"build : {system_info[-2]}\n" f"hw-code: {system_info[0]}" ) now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"Report date: {now}") for service_name, service in self.fc.services.items(): if service_name == 'any1': continue print() print('=' * 65) for action_name in service.actions: self.view_actionarguments(service_name, action_name) def add_arguments(parser): parser.add_argument('-r', '--reconnect', action='store_true', help='Reconnect and get a new ip') parser.add_argument('-R', '--reboot', action='store_true', help='Reboot the router') parser.add_argument('-s', '--services', action='store_true', help='List all available services') parser.add_argument('-S', '--serviceactions', nargs=1, help='List actions for the given service: ') parser.add_argument('-a', '--servicearguments', nargs=1, help='List arguments for the actions of a ' 'specified service: .') parser.add_argument('-A', '--actionarguments', nargs=2, help='List arguments for the given action of a ' 'specified service: . ' 'Lists also direction and data type of the ' 'arguments.') parser.add_argument('-c', '--complete', nargs='?', default=False, const=True, help='List the complete api of the router') def run_inspector(inspector, args): print_header(inspector.fc) if args.services: inspector.view_servicenames() elif args.serviceactions: inspector.view_actionnames(args.serviceactions[0]) elif args.servicearguments: inspector.view_actionnames(args.servicearguments[0], view_arguments=True) elif args.actionarguments: inspector.view_actionarguments(args.actionarguments[0], args.actionarguments[1]) elif args.complete: inspector.view_complete_api() elif args.reconnect: inspector.fc.reconnect() print('reconnect the router.') elif args.reboot: inspector.fc.reboot() print('reboot the router.') print() def execute(): args = get_cli_arguments(add_arguments) fc = get_instance(FritzConnection, args) inspector = FritzInspection(fc=fc) run_inspector(inspector, args) def main(): try: execute() except FritzAuthorizationError as err: print_common_exception_message(err) if __name__ == '__main__': main()