Hello,
I’m writing a plugin to control the Yamaha RX-A1000 receiver over IP. Unlike the Onkyo and Denon receivers which already have plugins and basically open an IO port and read / write serial commands, the Yamaha receivers use an HTTP POST request containing a body of XML data. And here in lies the problem - unlike the standard IO methods where the Action sends the request and Incoming handles the response, the request and response occur in the Action.
I’ve been trying to wrap my brain around the best method for handling this case for the last couple weeks. I’ve reviewed many of the published plugins for possible solutions, but I’ve come up empty. Do any coders have any suggestions how to / where best handle the responses?
Here’s an example to illustrate using the commands to power ON the Main Zone.
Request body:
<YAMAHA_AV cmd="PUT">
<Main_Zone>
<Power_Control>
<Power>On</Power>
</Power_Control>
</Main_Zone>
</YAMAHA_AV>
Response body:
<YAMAHA_AV rsp="PUT">
<Main_Zone>
<Power_Control>
<Power></Power>
</Power_Control>
</Main_Zone>
</YAMAHA_AV>
The response just acknowledges that request was valid and properly formatted (an HTTP error code would be returned if it wasn’t valid). To actually find out the state of the power, the following request is required:
<YAMAHA_AV cmd="GET">
<Main_Zone>
<Power_Control>
<Power>GetParam</Power>
</Power_Control>
</Main_Zone>
</YAMAHA_AV>
And the response:
<YAMAHA_AV rsp="GET">
<Main_Zone>
<Power_Control>
<Power>On</Power>
</Power_Control>
</Main_Zone>
</YAMAHA_AV>
So, two HTTP POST requests are required to turn the power on and verify it is completed. Now, unlike some serial protocols that may take time to respond, the response from the receiver is pretty much instantaneous, so while not ideal according to the wiki, the responses could be completely handled in the Action code with little performance impact.
Finally, the last item I’m considering is checking the status before sending the command. For example, if the ON action is issued when the receiver is already ON, an onscreen display shows on the TV. A simple check as to the status first, would prevent unnecessary commands from being sent (and the onscreen notifications). Is it best to just add another HTTP request, or should there be a service written that maintains the system status and is queried instead?
Here’s the power ON Code:
<action>
<serviceId>urn:micasaverde-com:serviceId:DiscretePower1</serviceId>
<name>On</name>
<run>
-- Power on
action = {"PUT", "Main_Zone", "Power_Control", "Power", "On"}
sendCommand(action)
</run>
</action>
And the functions:
local ipAddress
local YAMAHACTRLURL = "/YamahaRemoteControl/ctrl"
local http = require("socket.http")
function log(message)
luup.log("YamahaReceiver: " ..message)
end
function createRequest(getORput, zone, area, func, cmd)
local body = '<YAMAHA_AV cmd="'..getORput..'"><'..zone..'><'..area..'><'..func..'>'..cmd..'</'..func..'></'..area..'></'..zone..'></YAMAHA_AV>'
return body
end
function sendCommand(action)
luup.log("Yamaha Send Command")
http.TIMEOUT = 5
local requestBody = createRequest(action[1], action[2], action[3], action[4], action[5])
log("Body:"..requestBody)
address = "http://"..ipAddress..YAMAHACTRLURL
result, status = http.request(address, requestBody)
log("Status"..status)
log("Result"..result)
if (status == 200) then
return true
end
return false
end
Given all that, any recommendations?
Thanks!