Home AMX User Forum NetLinx Studio

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:
<?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

Comments

  • AMXJeffAMXJeff Posts: 450
    My understanding is that you submit the XML sheet as part of a "HTTP Post".

    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>
  • Thank you very much AMXJeff.

    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"
    } 
    
    
    --John
    
  • AMXJeffAMXJeff Posts: 450
    I think you need one additional CRLF at the end of the header section to let the HTTP server know your done with the header and expect the content, so two sets. I think you only count the xml sheet data, spaces included, when you come up with the length information.

    Since 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           *)
    (***********************************************************)
    
    
    
  • WOW!

    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
  • AMXJeffAMXJeff Posts: 450
    Thanks, only spent a few moments on it, just copied code from an existing project that used HTTP Post... Hope it works out for you...
Sign In or Register to comment.