Package: aioupnp
[UPnP for asyncioaioupnpis a python 3.6-8 library and command line tool to interact with UPnP gateways using asyncio.aioupnprequires thenetifacesanddefusedxmlmodules.Supported devicesInstallationVerify python is version 3.6-8python --versionInstallation for normal usagepip install aioupnpInstallation for developmentgit clone https://github.com/lbryio/aioupnp.git
cd aioupnp
pip install -e .Usageaioupnp [-h] [--debug_logging] [--interface=<interface>] [--gateway_address=<gateway_address>]
        [--lan_address=<lan_address>] [--timeout=<timeout>]
        [(--<case sensitive m-search header>=<value>)...]
        command [--<arg name>=<arg>]...Commandshelpget_external_ipm_searchadd_port_mappingget_port_mapping_by_indexget_redirectsget_specific_port_mappingdelete_port_mappingget_next_mappinggather_debug_infoTo get the documentation for a commandaioupnp help get_external_ipTo get the external ip addressaioupnp get_external_ipTo list the active port mappings on the gatewayaioupnp get_redirectsTo set up a TCP port mappingaioupnp add_port_mapping --external_port=1234 --internal_port=1234 --lan_address=<lan_addr> --description=test --protocol=TCPTo delete a TCP port mappingaioupnp delete_port_mapping --external_port=1234 --protocol=TCPM-Search headersUPnP uses a multicast protocol (SSDP) to locate the gateway. Gateway discovery is automatic by default, but you may provide specific headers for the search to use to override automatic discovery.If m-search headers are provided as keyword arguments then all of the headers to be used must be provided, in the order they are to be used. For example:aioupnp --HOST=239.255.255.250:1900 --MAN=\"ssdp:discover\" --MX=1 --ST=upnp:rootdevice m_searchUsing non-default network interfacesBy default, the network device will be automatically discovered. The interface may instead be specified with the--interface, provided before the command to be run. The gateway used on the interface network may be specified with the--gateway_addressargument.aioupnp --interface=wlp4s0 --gateway_address=192.168.1.6 m_searchExample usage from pythonfrom aioupnp.upnp import UPnP

async def main():
    upnp = await UPnP.discover()
    print(await upnp.get_external_ip())
    print(await upnp.get_redirects())

    print("adding a port mapping")
    await upnp.add_port_mapping(1234, 'TCP', 1234, upnp.lan_address, 'test mapping')
    print(await upnp.get_redirects())

    print("deleting the port mapping")
    await upnp.delete_port_mapping(1234, 'TCP')
    print(await upnp.get_redirects())


asyncio.run(main())TroubleshootingIfaioupnpis failing with m-search timeouts this means the UPnP gateway (the router) isn't being found at all. To see if this error is expected try running m_search with debug logging, which will print out the packets sent and received:aioupnp --debug_logging m_searchIf you only see packets being sent or the replies are only from devices that aren't your router (smart devices, speakers, etc), then there are three options:your router does not support UPnP (this is unlikely)UPnP is turned off in the web gui for your router (more likely)aioupnphas a bug (very likely if you don't see your router manufacturer doing well in the supported devices table)If you see replies from the router but it still fails, then it's likely a bug in aioupnp.If there are no replies and UPnP is certainly turned on, then a local firewall is the likely culprit.Sending a bug reportIf it still doesn't work, you can send a bug report using an included script. This script will try finding the UPnP gateway usingaioupnpas well asminiupnpcand then try add and remove a port mapping using each library. The script does this while capturing the packets sent/received, which makes figuring out what went wrong possible. The script will create a file with this packet capture (aioupnp-bug-report.json) and automatically send it.Note: the bug report script currently does not work on MacOSgit clone https://github.com/lbryio/aioupnp.git
cd aioupnp
python3 -m pip install -e .

python3 -m pip install --user certifi aiohttp miniupnpc
sudo -E python3 generate_bug_report.pyLicenseThis project is MIT licensed. For the full license, seeLICENSE.ContactThe primary contact for this project is@jackrobison