IP Control of Yamaha RXZ11?
Hi Everyone,
I'm currently in Hawaii on a project and I'm running on just a few hours of sleep... Here's the question:
The new RXZ11 can be controlled via IP. It seems to be as simple as sending an XML string to it. I'm a little behind the 8 ball on time, but I'm wondering if there's anything more than just opening the IP client and sending the XML string? The documentation from Yamaha isn't very clear to me.
Here's the command that their spreadsheet generates:
Can I just do the following or is there something more fancy I need to do?
-John
I'm currently in Hawaii on a project and I'm running on just a few hours of sleep... Here's the question:
The new RXZ11 can be controlled via IP. It seems to be as simple as sending an XML string to it. I'm a little behind the 8 ball on time, but I'm wondering if there's anything more than just opening the IP client and sending the XML string? The documentation from Yamaha isn't very clear to me.
Here's the command that their spreadsheet generates:
<?xml version="1.0" encoding="utf-8"?>
<YAMAHA_AV cmd="PUT">
<Main_Zone>
<Power_Control>
<Power>On</Power>
</Power_Control>
</Main_Zone>
</YAMAHA_AV>
Can I just do the following or is there something more fancy I need to do?
DEFINE_START
IP_CLIENT_OPEN (2,cYamahaIPAddress,80,1)
DEFINE_EVENT
BUTTON_EVENT[dvYamahaRXZ11,nPower_On]
{
PUSH :
{
SEND_STRING dvYamahaRXZ11, "'<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="PUT"><Main_Zone><Power_Control><Power>On</Power></Power_Control></Main_Zone></YAMAHA_AV>'"
}
}
-John
0
Comments
POST /avctrl/ctrl.cgi HTTP/1.1
Content-Type: text/plain
Content-length: 114
HOST: 192.168.2.74
<?xml version="1.0" encoding="utf-8"?>
<YAMAHA_AV cmd="PUT">
<System>
<Mem_Guard>Off</Mem_Guard>
</System>
</YAMAHA_AV>
I won't get a lot of tries to get this to work because of our time crunch, but does the following look somewhat correct? I'm also curious about the content-length... can I calculate that just by counting the characters and ignoring the spaces, and also do I count the last CR, LF?
DEFINE_EVENT DATA_EVENT[dvYamahaReceiver] { ONLINE: { IP_CLIENT_OPEN (2,cYamahaIPAddress,80,1) } } BUTTON_EVENT(tpYahamaReceiver,nPower_On) { SEND_STRING dvYamahaReceiver," 'POST /avctrl/ctrl.cgi HTTP/1.1',13,10, 'Content-length: 141',13,10, 'Content-Type: text/plain',13,10, 'Host: ',cYamahaRXZ11IPAddress,13,10, '<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="PUT"><Main_Zone><Power_Control><Power>On</Power></Power_Control></Main_Zone></YAMAHA_AV>',13,10" } --JohnSince you do not have alot of time with this for testing, I think you may find it hard to test with your example. This example should help, although it has not been tested, will give you more of a chance to see it working quicker.
PROGRAM_NAME='HTTP Post' (***********************************************************) (***********************************************************) (* FILE_LAST_MODIFIED_ON: 04/05/2006 AT: 09:00:25 *) (***********************************************************) (* System Type : NetLinx *) (***********************************************************) (* REV HISTORY: *) (***********************************************************) (* $History: $ *) (***********************************************************) (* DEVICE NUMBER DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_DEVICE dvSocket = 0:2:0 vdvSocket = 33001:1:0 dvTP = 10001:1:0; (***********************************************************) (* CONSTANT DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_CONSTANT // SERVER STUFF SERVER_IP_PORT = 80 CHAR cIPAddress[100] = '192.168.30.10' // MAX STUFF MAX_QUEUE_ITEMS = 25; MAX_LENGTH_MSG_STRING = 2048; MAX_BUFFER_SIZE = 10000; // COMM TRAFFIC IP_TIMEOUT = 50; IS_ONLINE = 250; BUSY = 251; (***********************************************************) (* DATA TYPE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_TYPE (***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_VARIABLE nDebugMode // QUEUE /////////////////////////////////////////////////// VOLATILE INTEGER cQueueHead = 1; VOLATILE INTEGER cQueueTail = 1; VOLATILE INTEGER cQueueReady = 1; VOLATILE INTEGER cQueueHasItems = 0; VOLATILE CHAR cQueue[MAX_QUEUE_ITEMS][MAX_LENGTH_MSG_STRING]; VOLATILE CHAR cCurrentMessage[MAX_LENGTH_MSG_STRING]; // BUFFER ////////////////////////////////////////////////// VOLATILE CHAR cBuffer[MAX_BUFFER_SIZE]; (***********************************************************) (* LATCHING DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_LATCHING (***********************************************************) (* MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_MUTUALLY_EXCLUSIVE (***********************************************************) (* SUBROUTINE/FUNCTION DEFINITIONS GO BELOW *) (***********************************************************) (**************************************) (* Call Name: PushQueue *) (* Function: Adds comamnd to the queue*) (* Return: n/a *) (**************************************) DEFINE_FUNCTION PushQueue(CHAR cQueue[][],Char cCmd[]) { IF (cQueueHead = MAX_LENGTH_ARRAY(cQueue)) { IF (cQueueTail <> 1) { cQueueHead = 1 cQueue[cQueueHead] = cCmd ON[cQueueHasItems] } } ELSE IF (cQueueTail <> cQueueHead + 1) { cQueueHead = cQueueHead + 1 cQueue[cQueueHead] = cCmd ON[cQueueHasItems] } } (**************************************) (* Call Name: PopQueue *) (* Function: Removes from the queue *) (* Return: n/a *) (**************************************) DEFINE_FUNCTION CHAR[MAX_LENGTH_MSG_STRING] PopQueue(CHAR cQueue[][]) { IF (cQueueHasItems AND cQueueReady) { OFF[cQueueReady] IF (cQueueTail = MAX_LENGTH_ARRAY(cQueue)) cQueueTail = 1 ELSE cQueueTail = cQueueTail + 1 IF (cQueueTail = cQueueHead) OFF[cQueueHasItems] ON[cQueueReady] RETURN cQueue[cQueueTail]; } } (**************************************) (* Call Name: NextMessageReady *) (* Function: Boolean, Ready? *) (* Return: n/a *) (**************************************) DEFINE_FUNCTION INTEGER NextMessageReady(Dev vdvSocket) { RETURN (cQueueHasItems == TRUE && cQueueReady == TRUE && [vdvSocket,IS_ONLINE] == 0 && [vdvSocket,BUSY] == 0); } (**************************************) (* Call Name: SendString *) (* Function: Sends Get Command to HTTP*) (* Return: n/a *) (**************************************) DEFINE_FUNCTION SendString(Dev dvSocket, DEV vdvSocket, CHAR cMessageContent[]) { STACK_VAR CHAR cHTTPHeader[MAX_LENGTH_MSG_STRING]; IF (LENGTH_STRING(cMessageContent) && [vdvSocket,IS_ONLINE]) { cHTTPHeader = "'POST /avctrl/ctrl.cgi HTTP/1.1',13,10"; cHTTPHeader = "cHTTPHeader,'Connection: close',13,10"; cHTTPHeader = "cHTTPHeader,'Content-length: ',ITOA(LENGTH_STRING(cMessageContent)),13,10"; cHTTPHeader = "cHTTPHeader,'Content-type: text/plain',13,10"; cHTTPHeader = "cHTTPHeader,'Host: NetLinx',13,10" cHTTPHeader = "cHTTPHeader,13,10" // Extra Line Between Content // SEND HTTP POST REQUEST SEND_STRING dvSocket,"cHTTPHeader" SEND_STRING dvSocket,"cMessageContent,13,10" // CLEAR MESSAGE cMessageContent = ""; } } (**************************************) (* Call Name: HTTPOpen *) (* Function: Opens Socket *) (* Return: n/a *) (**************************************) DEFINE_FUNCTION HTTPOpen(Dev dvSocket,DEV vdvSocket, Char cIPAddress[], LONG lTimeout) { IP_CLIENT_OPEN(dvSocket.Port,cIPAddress,80,1); SET_PULSE_TIME(lTimeout) PULSE[vdvSocket,BUSY] SET_PULSE_TIME(5) } (**************************************) (* Call Name: CommServer *) (* Function: Communicats to HTTP *) (* Return: n/a *) (**************************************) DEFINE_FUNCTION CommServer(DEV dvSocket, DEV vdvSocket, CHAR cQueue[][]) { IF (NextMessageReady(vdvSocket)) { HTTPOpen(dvSocket, vdvSocket, cIPAddress, IP_TIMEOUT); cCurrentMessage = PopQueue(cQueue); } SendString(dvSocket, vdvSocket, cCurrentMessage); } (**************************************) (* Call Name: ParseHTTPBuffer *) (* Function: Parse HTTP Buffer *) (* Return: n/a *) (**************************************) DEFINE_FUNCTION ParseHTTPBuffer(CHAR cBuffer[]) { STACK_VAR LONG lHTTPCode; STACK_VAR CHAR cTrash[100]; cTrash = REMOVE_STRING(cBuffer,'HTTP/1.1',1); lHTTPCode = ATOI(cBuffer); SWITCH (lHTTPCode) { // Object moved CASE 302: { } // OK CASE 200: { } } } (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START CREATE_BUFFER dvSocket,cBuffer; (***********************************************************) (* THE EVENTS GO BELOW *) (***********************************************************) DEFINE_EVENT DATA_EVENT[dvSocket] { ONLINE: { ON[vdvSocket,IS_ONLINE] TOTAL_OFF[vdvSocket,BUSY] WAIT 50 'CANCEL' IP_CLIENT_CLOSE(dvSocket.Port); } STRING: { CANCEL_WAIT 'CANCEL' } OFFLINE: { IF (LENGTH_STRING(cBuffer)) ParseHTTPBuffer(cBuffer); CANCEL_WAIT 'CANCEL' OFF[vdvSocket,IS_ONLINE] } } BUTTON_EVENT[dvTP,1] { PUSH: { PushQueue(cQueue,'<?xml version="1.0" encoding="utf-8"?><YAMAHA_AV cmd="PUT"><System><Mem_Guard>Off</Mem_Guard></System></YAMAHA_AV>'); } } (***********************************************************) (* THE ACTUAL PROGRAM GOES BELOW *) (***********************************************************) DEFINE_PROGRAM CommServer(dvSocket,vdvSocket,cQueue) (***********************************************************) (* END OF PROGRAM *) (* DO NOT PUT ANY CODE BELOW THIS COMMENT *) (***********************************************************)Thanks AMXJeff, I wasn't expecting a whole code block! That's really nice of you. I'm back in San Diego now, I ended up having to use IR commands to get it to all work quickly. I'll be back out there in a few weeks, so I'll start on the IP programming in a few days. I'll take a look at the example you provided as a guideline, it looks pretty good. I'll post any results with the IP protocol as I get further along in the program.
Thanks again!
--John