如何使用 NodeMCU 将 HTTP SOAP 请求发送到本地 Sonos 设备?
How to send HTTP SOAP request to local Sonos device with NodeMCU?
如何向 Lua 中的 Sonos 扬声器发送简单的 HTTP POST/GET SOAP 请求?
我尝试过简单的 HTTP POST 和 GET 请求并成功,但我不知道从哪里开始 SOAP 请求。
注意:我是这方面的新手。我以前从未使用过 NodeMCU,也没有在 Lua 中编程过。不过我有使用其他语言的经验。
我知道如何用 C# 实现,Java 和 PHP。
这适用于 Postman:
HTTP Headers:
SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause
Content-Type:text/xml; charset="utf-8"
Host:192.168.0.10:1400
BODY:
<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 错误或其他什么?
我没有 Sonos 设备可以玩。因此,这不是 确认的 答案。
您的 content
变量中的字符串不是有效的 HTTP 请求。 Sonos 不理解它是 error code 401 means "invalid action".
您需要单独的 HTTP headers 和 \r\n
。需要在 HTTP body 之前放置一个额外的 \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......"
终于!我有它的工作!下面是让它工作的代码:
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
如何向 Lua 中的 Sonos 扬声器发送简单的 HTTP POST/GET SOAP 请求?
我尝试过简单的 HTTP POST 和 GET 请求并成功,但我不知道从哪里开始 SOAP 请求。
注意:我是这方面的新手。我以前从未使用过 NodeMCU,也没有在 Lua 中编程过。不过我有使用其他语言的经验。
我知道如何用 C# 实现,Java 和 PHP。
这适用于 Postman:
HTTP Headers:
SOAPAction:urn:schemas-upnp-org:service:AVTransport:1#Pause
Content-Type:text/xml; charset="utf-8"
Host:192.168.0.10:1400
BODY:
<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 错误或其他什么?
我没有 Sonos 设备可以玩。因此,这不是 确认的 答案。
您的 content
变量中的字符串不是有效的 HTTP 请求。 Sonos 不理解它是 error code 401 means "invalid action".
您需要单独的 HTTP headers 和 \r\n
。需要在 HTTP body 之前放置一个额外的 \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......"
终于!我有它的工作!下面是让它工作的代码:
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