You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于树莓派的IoT设备uPnP发布Web应用失败,求解决方案

问题:树莓派上通过UPnP发布Web应用无法被兼容设备发现

我正在用树莓派开发一款IoT设备,设备由同一树莓派上部署的Web应用控制。我想通过UPnP发布这个Web应用,让所有UPnP兼容设备能发现并打开它,但尝试后没成功。服务用Python 3编写,我试了iot-upnp模块,照着示例配置后,这个服务既没在PC端VLC显示,也没在安卓端DMS Explorer被发现。

以下是我的测试配置代码(仅用于验证功能,无实际业务逻辑):

import upnp
class UPNPAnnouncer(object):
    def __init__(self):
        self._loop = None
        self._device = upnp.Device({
            'deviceType': 'urn:sadmin-fr:device:demo:1',
            'friendlyName': 'UPnP Test',
            'uuid': '00a56575-78fa-40fe-b107-8f4b5043a2b0',
            'manufacturer': 'BONNET',
            'manufacturerURL': 'http://sadmin.fr'
        })
        self._service = upnp.Service({
            'serviceType': 'sadmin-fr:service:dummy',
            'serviceId': 'sadmin-fr:serviceId:1',
        })
        self._device.addService(self._service)
    def configure(self, loop):
        self._loop = loop
        self._server = upnp.Annoncer(self._device)
        self._server.initLoop(loop)
        loop.create_task(self._send_announces())
    async def _send_announces(self):
        while True:
            print("Notify upnp")
            self._server.notify()
            await asyncio.sleep(2)

请问我该怎么解决这个问题?


解决方案

别着急,我帮你梳理几个可能的问题点和修复步骤,应该能解决你的设备发现问题:

1. 改用标准UPnP设备/服务类型

你现在用的自定义设备类型urn:sadmin-fr:device:demo:1和服务类型sadmin-fr:service:dummy,虽然UPnP允许自定义,但很多客户端(比如VLC、DMS Explorer)只会优先识别标准UPnP设备类型。如果是要发布Web应用供设备访问,建议用urn:schemas-upnp-org:device:WebServer:1这类标准设备类型,同时补充对应Web访问的关键字段:

self._device = upnp.Device({
    'deviceType': 'urn:schemas-upnp-org:device:WebServer:1',
    'friendlyName': 'UPnP Test',
    'uuid': '00a56575-78fa-40fe-b107-8f4b5043a2b0',
    'manufacturer': 'BONNET',
    'manufacturerURL': 'http://sadmin.fr',
    # 必须添加这个字段,告诉客户端你的Web应用地址
    'presentationURL': 'http://你的树莓派局域网IP:端口号'  # 比如http://192.168.1.100:8080
})

2. 绑定正确的网络接口

树莓派可能有多个网络接口(比如有线eth0、无线wlan0),如果UPnP服务默认绑定到localhost或错误的接口,其他设备根本收不到通知。你可以手动指定局域网IP来初始化Announcer:

import socket

def configure(self, loop):
    self._loop = loop
    # 获取树莓派的局域网IP
    local_ip = socket.gethostbyname(socket.gethostname())
    # 绑定到指定IP
    self._server = upnp.Annoncer(self._device, listen_addr=local_ip)
    self._server.initLoop(loop)
    loop.create_task(self._send_announces())

3. 检查网络和防火墙设置

  • 树莓派的防火墙(比如ufw)可能阻断了UPnP的UDP广播端口(默认1900端口),需要开放:
sudo ufw allow 1900/udp
sudo ufw reload
  • 确保树莓派和测试设备(PC、安卓)在同一局域网,没有VLAN或子网隔离;
  • 可以用tcpdump抓包验证UPnP通知是否发出:
sudo tcpdump -i any udp port 1900

运行代码后,看看是否有NOTIFY包发送到组播地址239.255.255.250。

4. 完善事件循环的完整流程

你的代码没展示事件循环的启动部分,确保正确初始化并启动asyncio循环:

import asyncio

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    announcer = UPNPAnnouncer()
    announcer.configure(loop)
    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        loop.close()

5. 验证iot-upnp模块的兼容性

如果以上步骤都试过还是不行,可能是iot-upnp模块的实现存在遗漏。你可以先升级到最新版本试试:

pip install --upgrade iot-upnp

如果还是不行,建议换用更成熟的UPnP服务端库,比如Coherence或者基于Twisted的UPnP实现,这类库对UPnP规范的支持更完整。

内容的提问来源于stack exchange,提问作者Rastersoft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 21:42:34