Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't follow typical usage examples from readme #42

Open
R0CKH0PP3R opened this issue Jan 25, 2023 · 5 comments
Open

Can't follow typical usage examples from readme #42

R0CKH0PP3R opened this issue Jan 25, 2023 · 5 comments

Comments

@R0CKH0PP3R
Copy link

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'.
@brostosjoined
Copy link

brostosjoined commented Aug 14, 2023

@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'>]

@rytilahti
Copy link
Contributor

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.

@sergiomb2
Copy link

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 ?

@joncox123
Copy link

joncox123 commented Apr 29, 2024

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)

@brostosjoined
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants