aioupnp/txupnp/soap.py

80 lines
3.5 KiB
Python
Raw Normal View History

2018-07-29 04:08:24 +02:00
import logging
2018-09-25 20:52:29 +02:00
import netifaces
2018-07-29 04:08:24 +02:00
from twisted.internet import defer
from txupnp.ssdp import SSDPFactory
from txupnp.scpd import SCPDCommandRunner
from txupnp.gateway import Gateway
2018-07-29 05:06:17 +02:00
from txupnp.fault import UPnPError
2018-07-31 22:53:08 +02:00
from txupnp.constants import UPNP_ORG_IGD
2018-07-29 04:08:24 +02:00
log = logging.getLogger(__name__)
class SOAPServiceManager(object):
2018-09-25 20:52:29 +02:00
def __init__(self, reactor, treq_get=None):
2018-07-29 04:08:24 +02:00
self._reactor = reactor
2018-09-25 20:52:29 +02:00
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']
2018-07-29 23:32:14 +02:00
self.sspd_factory = SSDPFactory(self._reactor, self.lan_address, self.router_ip)
2018-07-29 04:08:24 +02:00
self._command_runners = {}
2018-07-31 22:53:08 +02:00
self._selected_runner = UPNP_ORG_IGD
2018-09-25 20:52:29 +02:00
self._treq_get = treq_get
2018-07-29 04:08:24 +02:00
@defer.inlineCallbacks
2018-07-29 23:32:14 +02:00
def discover_services(self, address=None, timeout=30, max_devices=1):
2018-07-29 04:08:24 +02:00
server_infos = yield self.sspd_factory.m_search(
2018-07-29 23:32:14 +02:00
address or self.router_ip, timeout=timeout, max_devices=max_devices
2018-07-29 04:08:24 +02:00
)
locations = []
for server_info in server_infos:
2018-07-29 04:33:45 +02:00
if 'st' in server_info and server_info['st'] not in self._command_runners:
2018-07-29 04:08:24 +02:00
locations.append(server_info['location'])
gateway = Gateway(**server_info)
yield gateway.discover_services()
2018-09-25 20:52:29 +02:00
command_runner = SCPDCommandRunner(gateway, self._reactor, self._treq_get)
2018-07-29 04:08:24 +02:00
yield command_runner.discover_commands()
self._command_runners[gateway.urn.decode()] = command_runner
2018-07-29 04:33:45 +02:00
elif 'st' not in server_info:
log.error("don't know how to handle gateway: %s", server_info)
continue
2018-08-08 01:02:56 +02:00
defer.returnValue(len(self._command_runners) > 0)
2018-07-29 04:08:24 +02:00
def set_runner(self, urn):
if urn not in self._command_runners:
raise IndexError(urn)
self._command_runners = urn
def get_runner(self):
2018-07-29 05:06:17 +02:00
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:
2018-07-29 05:19:22 +02:00
raise UPnPError("no devices found")
2018-07-29 04:08:24 +02:00
return self._command_runners[self._selected_runner]
def get_available_runners(self):
return self._command_runners.keys()
2018-07-30 23:48:20 +02:00
2018-08-01 22:29:00 +02:00
def debug(self, include_gateway_xml=False):
2018-07-30 23:48:20 +02:00
results = []
for runner in self._command_runners.values():
gateway = runner._gateway
2018-08-01 22:29:00 +02:00
info = gateway.debug_device(include_xml=include_gateway_xml)
2018-07-31 22:53:08 +02:00
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
2018-07-30 23:48:20 +02:00
results.append(info)
return results