首页 文章

如何使用NodeMCU向本地Sonos设备发送HTTP SOAP请求?

提问于
浏览
0

如何向Lua中的Sonos扬声器发送简单的HTTP POST / GET SOAP请求?

我已经尝试了简单的HTTP POST和GET请求,但我不知道从哪里开始使用SOAP请求 .

注意:我是新手 . 我以前从未使用过NodeMCU,也没有在Lua中编程 . 我有其他语言的经验 .

我知道如何在C#,Java和PHP中完成它 .

这适用于Postman:

HTTP标头:

SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause
Content-Type:text/xml; charset="utf-8"
Host:192.168.0.10:1400

身体:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body><u:Pause xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID></u:Pause></s:Body></s:Envelope>

我做的是这个,它不起作用:

sendRequest("192.168.0.10")
function sendRequest(url)
    print("Sending request to Sonos Playbar...")
    sk = net.createConnection(net.TCP, 0)
    sk:on("receive", function(sck, c) print(c) end )
    sk:on("connection", function(sck, c)

        print("\r\n\r\n\r\n")

        -- HTTP 405: Method not allowed
        -- sck:send("POST / HTTP/1.1\r\nHost: "..url..":1400\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")

        -- HTTP 500, UPnP 402: Invalid arguments
        -- sck:send("POST /MediaRenderer/AVTransport/Control HTTP/1.1\r\nHost: "..url..":1400\r\nSOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\nConnection: keep-alive\r\n\r\nAccept: */*\r\n\r\n")


        local content = nil;
    content = "POST /MediaRenderer/AVTransport/Control\r\n"
    content = content.."Host:192.168.0.10:1400\r\n"
    content = content.."Content-Type:text/xml; charset=utf-8\r\n"
    content = content.."SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n"
    content = content.."\r\n"

    -- SOAP Body
    content = content.."<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
    content = content.." s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
    content = content.."<s:Body>"
    content = content.."<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">"
    content = content.."<InstanceID>0</InstanceID>"
    content = content.."</u:Pause>"
    content = content.."</s:Body>"
    content = content.."</s:Envelope>"
    -- SOAP Body End

        print(content.."\r\n\r\n\r\n")

        sck:send(content);
    end)
    sk:connect(1400, url)
end

我得到了Sonos播放器的响应:

HTTP/1.1 500 Internal Server Error
CONTENT-LENGTH: 347
CONTENT-TYPE: text/xml; charset="utf-8"
EXT: 
Server: Linux UPnP/1.0 Sonos/34.16-37101 (ZPS9)
Connection: close

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <s:Body>
        <s:Fault>
            <faultcode>s:Client</faultcode>
                <faultstring>UPnPError</faultstring>
                    <detail>
                        <UPnPError xmlns="urn:schemas-upnp-org:control-1-0">
                            <errorCode>401</errorCode>
                        </UPnPError>
                    </detail>
        </s:Fault>
    </s:Body>
</s:Envelope>

我究竟做错了什么?我基本上复制并粘贴了文本 . 也许它是 Headers 的顺序?也许我宣称 Headers 错了或什么?

2 回答

  • 1

    我没有确认答案 .

    content 变量中的字符串不是有效的HTTP请求 . Sonos不理解为error code 401 means "invalid action" .

    您需要使用 \r\n 的单独HTTP标头 . 需要在HTTP正文之前放置一个额外的 \r\n . 因此,我希望你的 content 应该是:

    "POST http://192.168.0.10:1400/MediaRenderer/AVTransport/Control\r\n
    SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n
    Content-Type:text/xml; charset=\"utf-8\"\r\n
    Host:192.168.0.10:1400\r\n\r\n
    <s:Envelope xmlns:s=\"http://schemas.xml......"
    
  • 0

    最后!我有它的工作!下面是让它工作的代码:

    sendRequest("192.168.0.10")
    function sendRequest(url)
        print("Sending request to Sonos Playbar...")
        local content = nil;
        content = "";
        -- SOAP Body
        content = content.."<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""
        content = content.." s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
        content = content.."<s:Body>"
        content = content.."<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">"
        content = content.."<InstanceID>0</InstanceID>"
        content = content.."</u:Pause>"
        content = content.."</s:Body>"
        content = content.."</s:Envelope>"
        -- SOAP Body End
    
        http.post("http://"..url..":1400/MediaRenderer/AVTransport/Control",
            'Content-Type: text/xml; charset="utf-8"\r\n'..
            'Host:'..url..':1400\r\n'..
            'SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause\r\n',
            content, function(code, data)
                if(code < 0) then
                    print("HTTP request failed with code "..code)
                else
                    print(code, data)
                end
            end)
    end
    

相关问题