aioupnp/txupnp/soap.py
2018-09-25 14:52:29 -04:00

79 lines
3.5 KiB
Python

import logging
import netifaces
from twisted.internet import defer
from txupnp.ssdp import SSDPFactory
from txupnp.scpd import SCPDCommandRunner
from txupnp.gateway import Gateway
from txupnp.fault import UPnPError
from txupnp.constants import UPNP_ORG_IGD
log = logging.getLogger(__name__)
class SOAPServiceManager(object):
def __init__(self, reactor, treq_get=None):
self._reactor = reactor
self.router_ip, self.iface_name = netifaces.gateways()['default'][netifaces.AF_INET]
self.lan_address = netifaces.ifaddresses(self.iface_name)[netifaces.AF_INET][0]['addr']
self.sspd_factory = SSDPFactory(self._reactor, self.lan_address, self.router_ip)
self._command_runners = {}
self._selected_runner = UPNP_ORG_IGD
self._treq_get = treq_get
@defer.inlineCallbacks
def discover_services(self, address=None, timeout=30, max_devices=1):
server_infos = yield self.sspd_factory.m_search(
address or self.router_ip, timeout=timeout, max_devices=max_devices
)
locations = []
for server_info in server_infos:
if 'st' in server_info and server_info['st'] not in self._command_runners:
locations.append(server_info['location'])
gateway = Gateway(**server_info)
yield gateway.discover_services()
command_runner = SCPDCommandRunner(gateway, self._reactor, self._treq_get)
yield command_runner.discover_commands()
self._command_runners[gateway.urn.decode()] = command_runner
elif 'st' not in server_info:
log.error("don't know how to handle gateway: %s", server_info)
continue
defer.returnValue(len(self._command_runners) > 0)
def set_runner(self, urn):
if urn not in self._command_runners:
raise IndexError(urn)
self._command_runners = urn
def get_runner(self):
if self._command_runners and not self._selected_runner in self._command_runners:
self._selected_runner = list(self._command_runners.keys())[0]
if not self._command_runners:
raise UPnPError("no devices found")
return self._command_runners[self._selected_runner]
def get_available_runners(self):
return self._command_runners.keys()
def debug(self, include_gateway_xml=False):
results = []
for runner in self._command_runners.values():
gateway = runner._gateway
info = gateway.debug_device(include_xml=include_gateway_xml)
commands = runner.debug_commands()
service_result = []
for service in info['services']:
service_commands = []
unavailable = []
for command, service_type in commands['available'].items():
if service['serviceType'] == service_type:
service_commands.append(command)
for command, service_type in commands['failed'].items():
if service['serviceType'] == service_type:
unavailable.append(command)
services_with_commands = dict(service)
services_with_commands['available_commands'] = service_commands
services_with_commands['unavailable_commands'] = unavailable
service_result.append(services_with_commands)
info['services'] = service_result
results.append(info)
return results