Open R0CKH0PP3R opened 1 year ago
@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'>]
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.
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 ?
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)
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
After installing with pip as user, I get the following when trying the usage examples: