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

Windows下Python实现SSDP组播发现Yeelight设备失效问题排查

SSDP组播发现Yeelight设备Windows端失效问题

我正在开发一款通过SSDP组播发现Yeelight设备的应用,按照设备规范,需要向239.255.255.250的1982端口发送M-SEARCH消息。这段代码在两台MacOS设备上运行正常,但Windows端原本能用,隔了两天突然失效。我怀疑是Windows系统拦截了相关操作,但找不到问题根源。已经试过在防火墙添加例外、关闭杀毒软件,问题还是没解决。

相关Python代码

import socket
import threading

from pprint import pprint
from time import sleep
from colorama import Fore, Style

discoveryAddress = ("239.255.255.250", 1982)
discoveryMessage = "M-SEARCH * HTTP/1.1\r\n" + "HOST: 239.255.255.250:1982\r\n" + \
    "MAN: \"ssdp:discover\"\r\n" + "ST: wifi_bulb\r\n"


def doSearch():
    ssdpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    ssdpSocket.sendto(str.encode(discoveryMessage), discoveryAddress)

    while True:
        response = ssdpSocket.recvfrom(1024)
        msg = format(response[0])
        formattedResponse = formatResponse(msg.split('\\r\\n'))

        print("hi")

        print(Fore.GREEN, "Received response")
        print(Fore.WHITE, formattedResponse, '\n')


def formatResponse(response: list) -> list:
    result = []
    filteredAttr = ['HTTP', 'Location:', 'power:']

    for s in response:
        for attr in filteredAttr:
            if attr in s:
                result.append(s)

    return result


doSearch()

排查与修复建议

  • 补全组播套接字必要配置:Windows对UDP组播的套接字配置要求更严格,原代码缺少组播成员加入和地址复用设置,添加以下代码:
    ssdpSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # 加入组播组,允许接收组播响应
    ssdpSocket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, 
                          socket.inet_aton("239.255.255.250") + socket.inet_aton("0.0.0.0"))
    # 设置超时,避免无限阻塞
    ssdpSocket.settimeout(10)
    
  • 修正M-SEARCH消息格式:SSDP要求消息末尾必须有一个空行(额外的\r\n),否则设备可能不识别。修改消息定义:
    discoveryMessage = "M-SEARCH * HTTP/1.1\r\n" + "HOST: 239.255.255.250:1982\r\n" + \
        "MAN: \"ssdp:discover\"\r\n" + "ST: wifi_bulb\r\n\r\n"
    
  • 修复响应解析逻辑:原代码用format(response[0])处理字节数据会引入多余的b'和转义符,导致分割错误,改为直接解码:
    msg = response[0].decode('utf-8')
    formattedResponse = formatResponse(msg.split('\r\n'))
    
  • 检查网络适配器绑定:如果Windows切换了网络(如从有线到无线),可以指定套接字绑定到当前活跃网卡的本地IP,避免组播包发送到错误适配器:
    ssdpSocket.bind(("192.168.1.100", 0))  # 替换为你的实际本地IP
    
  • 抓包验证流量:用Wireshark抓udp port 1982的包,确认M-SEARCH消息是否发出,以及Yeelight设备是否返回响应。如果没收到响应,排查设备是否在同一网段、是否开启了SSDP发现;如果收到响应但代码没捕获,检查套接字配置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:05:38