upnpclient icon indicating copy to clipboard operation
upnpclient copied to clipboard

Can't follow typical usage examples from readme

Open R0CKH0PP3R opened this issue 2 years ago • 5 comments

After installing with pip as user, I get the following when trying the usage examples:


Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import upnpclient
>>> devices = upnpclient.discover()
>>> devices
[<Device 'PiFi (UpMpd AV)'>, <Device 'Focal UpMpd AV'>, <Device 'Plex Media Server: odroid'>, <Device 'PiFi (UpMpd OH)'>, <Device 'WFADevice'>, <Device 'BT Home Hub 6.0A'>, <Device 'Focal UpMpd OH'>]
>>> d = devices[0]
>>> d.WANIPConn1.GetStatusInfo()
Traceback (most recent call last):
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 148, in __getattr__
    return self.service_map[name]
KeyError: 'WANIPConn1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 150, in __getattr__
    raise AttributeError("No attribute or service found with name %r." % name)
AttributeError: No attribute or service found with name 'WANIPConn1'.
>>> d.services
[<Service service_id='urn:upnp-org:serviceId:AVTransport'>, <Service service_id='urn:upnp-org:serviceId:RenderingControl'>, <Service service_id='urn:upnp-org:serviceId:ConnectionManager'>]
>>> d.Layer3Forwarding1.actions
Traceback (most recent call last):
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 148, in __getattr__
    return self.service_map[name]
KeyError: 'Layer3Forwarding1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 150, in __getattr__
    raise AttributeError("No attribute or service found with name %r." % name)
AttributeError: No attribute or service found with name 'Layer3Forwarding1'.

R0CKH0PP3R avatar Jan 25 '23 17:01 R0CKH0PP3R

@R0CKH0PP3R Could you show the output of

print(d.services)

This is my output

[<Service service_id='urn:upnp-org:serviceId:L3Forwarding1'>, <Service service_id='urn:upnp-org:serviceId:WANCommonIFC1'>, <Service service_id='urn:upnp-org:serviceId:WANIPConn1'>]

brostosjoined avatar Aug 14 '23 11:08 brostosjoined

WANIPConn1 is found commonly only on routers while the first device your list sounds like an AV device (<Device 'PiFi (UpMpd AV)'>). You can use services to access the list of available services for that device like mentioned by @brostosjoined, and use the last part of the service_id field to access the service by name.

The second last element in your devices list (the bt home hub) is something that might expose the WANIPConn1, if you want to follow the README instructions.

rytilahti avatar Aug 14 '23 12:08 rytilahti

I have the same problem:

import upnpclient
d = upnpclient.Device("http://192.168.1.108:8200/rootDesc.xml")
d.services

[<Service service_id='urn:upnp-org:serviceId:ContentDirectory'>,
<Service service_id='urn:upnp-org:serviceId:ConnectionManager'>,
<Service service_id='urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar'>]

after this what I can do ? how I list / browse the server ?

sergiomb2 avatar Mar 17 '24 21:03 sergiomb2

After installing with pip as user, I get the following when trying the usage examples:


Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import upnpclient
>>> devices = upnpclient.discover()
>>> devices
[<Device 'PiFi (UpMpd AV)'>, <Device 'Focal UpMpd AV'>, <Device 'Plex Media Server: odroid'>, <Device 'PiFi (UpMpd OH)'>, <Device 'WFADevice'>, <Device 'BT Home Hub 6.0A'>, <Device 'Focal UpMpd OH'>]
>>> d = devices[0]
>>> d.WANIPConn1.GetStatusInfo()
Traceback (most recent call last):
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 148, in __getattr__
    return self.service_map[name]
KeyError: 'WANIPConn1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 150, in __getattr__
    raise AttributeError("No attribute or service found with name %r." % name)
AttributeError: No attribute or service found with name 'WANIPConn1'.
>>> d.services
[<Service service_id='urn:upnp-org:serviceId:AVTransport'>, <Service service_id='urn:upnp-org:serviceId:RenderingControl'>, <Service service_id='urn:upnp-org:serviceId:ConnectionManager'>]
>>> d.Layer3Forwarding1.actions
Traceback (most recent call last):
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 148, in __getattr__
    return self.service_map[name]
KeyError: 'Layer3Forwarding1'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ahaslam/.local/lib/python3.10/site-packages/upnpclient/upnp.py", line 150, in __getattr__
    raise AttributeError("No attribute or service found with name %r." % name)
AttributeError: No attribute or service found with name 'Layer3Forwarding1'.

I figured out a solution. Its a little more complicated, as I'm not sure what happened to the API, as it seems to have changed a bit since the README was written. However, I developed and tested this code for my TP-Link ER7206 router, and it works fine. The process is slightly more cumbersome, but not too bad.

"""
Configures your home router to allow incoming connections to the PyBolo server, using the IGD/UPnP protocol.
"""

import upnpclient
import socket


class BoloUPnP:
    def __init__(self):
        self.router = None
        self.ip = None

        self.findRouter()

    # Search for a UPnP router with WAN connection
    def findRouter(self):
        print("Searching for UPnP router devices with WAN connection...", flush=True)
        devices = upnpclient.discover()
        for device in devices:
            WANIPConnection = getattr(device, "WANIPConnection", None)
            if callable(WANIPConnection):
                try:
                    ip = WANIPConnection.GetExternalIPAddress()["NewExternalIPAddress"]
                except KeyError as e:
                    print("BoloUPnP::findRouter: Error getting WAN IP address: %s" % str(e), flush=True)
                    continue
                print(
                    "BoloUPnP::findRouter: Found router %s with external IP %s" % (device.model_description, ip),
                    flush=True,
                )
                self.router = device
                self.ip = ip
        if self.router is None:
            print("BoloUPnP::findRouter: Failed to find any UPnP WAN routers", flush=True)

    # Open a port on the router
    def openPort(self, port, durationSeconds=21600):
        if self.router is None:
            print("BoloUPnP::openPort: No router found, please try calling findRouter first/again.", flush=True)
            return

        hostname = socket.gethostname()
        myIPAddress = socket.gethostbyname(hostname)

        AddPortMapping = getattr(self.router.WANIPConnection, "AddPortMapping", None)
        if callable(AddPortMapping):
            AddPortMapping(
                NewRemoteHost="0.0.0.0",
                NewExternalPort=port,
                NewProtocol="TCP",
                NewInternalPort=port,
                NewInternalClient=myIPAddress,
                NewEnabled="1",
                NewPortMappingDescription="PyBolo Server",
                NewLeaseDuration=durationSeconds,
            )
            print("BoloUPnP::openPort: Opened port %d to local IP %s" % (port, myIPAddress), flush=True)
        else:
            print("BoloUPnP::openPort: could not open a port!", flush=True)


if __name__ == "__main__":
    pnp = BoloUPnP()
    pnp.openPort(6901, durationSeconds=360)

joncox123 avatar Apr 29 '24 18:04 joncox123

import upnpclient
# Plucked from https://github.com/ethereum/upnp-port-forward/blob/master/upnp_port_forward/
WAN_SERVICE_NAMES = (
    "WANIPConn1",
    "WANIPConnection.1",  # Nighthawk C7800
    "WANPPPConnection.1",  # CenturyLink C1100Z
    "WANPPPConn1",  # Huawei B528s-23a
)

devices = upnpclient.discover()

if devices == []:
    print("No devices found")
try:
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # connect() for UDP doesn't send packets
    s.connect(('10.0.0.0', 0))
    local_ip = s.getsockname()[0]
    s.close()
except:
    pass
for upnp_dev in devices:
    for service in upnp_dev.services:
        if service.name in WAN_SERVICE_NAMES:
            service.AddPortMapping(
                NewRemoteHost="0.0.0.0",
                NewExternalPort=43210,
                NewProtocol="UDP",
                NewInternalPort=43210,
                NewInternalClient=local_ip,
                NewEnabled="1",
                NewPortMappingDescription="Bombsquad",
                NewLeaseDuration=14400)

have you tried this

brostosjoined avatar Apr 29 '24 20:04 brostosjoined