Home AMX User Forum NetLinx Modules & Duet Modules

First Module Please Help

13»

Comments

  • viningvining Posts: 4,368
    mncchartier wrote:
    So I should change these to SEND_COMMAND?
    No, leave them as SEND_STRING.

    dvViziaRF is an AMX port with something connected to it. When you send_command you are sending instructions or commands to the AMX port but when you send_string you are sending instructions or commands through the AMX port to the device connected to it.

    Does that help clarify this?
  • SEND_COMMANDS are normally for sending instruction to an AMX device that controls the AMX device. SEND_STRING is normally used to send instruction (protocol) through an AMX device to a 3rd party device (normally used with COM PORTS). You can use SEND_STRING when sending messages to the master because you want the string to go through the master to terminal or telnet session. When it comes to virtual devices, SEND_COMMAND and SEND_STRING send instruction to handlers of the DATA_EVENT. STRING and COMMAND recieve this data in DATA.TEXT.

    In Modules, SEND_COMMAND to the virtual device controls the code in the module that would in turn send a string to the controlled 3rd party device. The module would SEND_STRINGs back through the virtualDEVICE for feedback intreperted by the code in the module.
  • Thanks for the help on that. Ok so I can turn the light On but not off because of the feedback and did not have time to troubleshoot because the home owner had to leave. So I did some work on it at home. This is what I am receiving on the feedback from the lites

    Line 8 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<N004L255$0D$0A]

    I need the 004 and the 255 from that string, the 004 is the node and 255 means it is on. So here is what I came up with this is only for the individual lites.
    STRING:
        {
        	STACK_VAR CHAR cTemp[40]			// Max 40 characters in the received data from Vizia RS232 module
    	cTemp = (DATA.TEXT)
    	send_string 0, "cTemp"
    	SELECT
    	{
    	    ACTIVE (FIND_STRING(cTemp,'<N',1)):		//Looks to see if it is a Node Level Status
    	    {
    		cNode = REMOVE_STRING (cTemp,'0A<N',1)	//Makes cNode xxxLyyy,etc
    		SEND_STRING 0,"'Node',cNode"
    		nNode = ATOI(cNode)
    		cStatus = MID_STRING(cNode, 4,4)	//Makes Level Lyyy and cNode xxx
    		SEND_STRING 0,"'Level',cStatus"
    		IF (cStatus == 'L255')			//255 means lite is On
    		{
    		    nLiteStatus[nNode] = 1		//set LiteStatus to 1 for TP feedback
    		    SEND_STRING 0,"'cStatus On: ', nLiteStatus[nNode]"
    		}
    		ELSE
    		{
    		    nLiteStatus[nNode] = 0		//set LiteStatus to 0 for TP feedback
    		    SEND_STRING 0,"'cStatus Off: ', nLiteStatus[nNode]"
    		}
    	    }
    

    I appreciate everyones help and patience, and have a Happy Thanksgiving.
  • I was just reviewing the code above and that is not going to work. So this is what I receive

    Line 5 (18:18:02):: String From [5001:1:1]-[<E000$0D$0A]

    Line 6 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<E000$0D$0A<N004L255$0D$0A]

    Line 7 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<E000$0D$0A]

    Line 8 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<N004L255$0D$0A]

    I need the X000 for RF info, the Nxxx for the node number and the Lxxx for the light status. I was wondering if there is a string to array function in NS2. I have not found one so far. In a previous language I have used (not a control system) I could do a split string using a delimiter and go through the array looking for what I wanted. Sort of like this.

    This is how I would do it in AutoIT
    $stringArray = splitstring(data.text, "$0D$0A")      ;creates an array from a string using the delimiter
    For $i = 1 to $stringArray[0]                            ; For loop starting in array position 1, position 0 is an index
          If StringInString($stringArray[$i],"<N") Then     ;checks array element for <N
                  $node = stringmid($stringArray[$i], 2,3)  ;just like MID_STRING
                  $level = stringright($stringArray[$i], 3)    ;just like RIGHT_STRING 
          ElseIf StringInString($stringArray[$i], "<X") Then   ;and so on through the if statements
                  $rf = stringmid($stringArray[$i], 2, 3)
          ElseIf StringInString($stringArray[$i], "<E") Then
                  $error = stringmid($stringArray[$i], 2, 3)
          EndIf
    Next                                                               ;next element
    
  • viningvining Posts: 4,368
    Well it appears all your response end with $0D,$0A but in your string event handler you never test for a complete response before parsing.

    your code:
    STRING:
        {
        	STACK_VAR CHAR cTemp[17]				// Max 17 characters in the received data from Vizia RS232 module
    	cTemp = itoa(DATA.TEXT)
    	send_string 0, "cTemp"
    	SELECT
    	{
    	    ACTIVE (FIND_STRING(cTemp,'<N',1)):			//Looks to see if it is a Node Level Status
    	    {
    		REMOVE_STRING (cTemp,'<',1)			//Makes the message NxxxLyyy
    		SEND_STRING 0,"'Node',cTemp"
    		cNode = MID_STRING(cTemp,2,3)
    		nNode = ATOI(cNode)
    		cStatus = MID_STRING(cTemp,6,3)
    		nStatus = ATOI(cStatus)
    		IF (cStatus == '000')
    		{
    		    nLiteStatus[nNode] = 0
    		}
    		ELSE IF (cStatus == '255')
    		{
    		    nLiteStatus[nNode] = 1
    		}
    	    }
    	    ACTIVE (FIND_STRING(cTemp, '<G',1)):		//Looks to see if it is a Group Level Status
    	    {
    		REMOVE_STRING (cTemp,'<',1)			//cTemp is now GxxxLyyy
    		SEND_STRING 0,"'Group',cTemp"
    	    }
    	    ACTIVE (FIND_STRING(cTemp, '<X',1)):		//Looks to see if it is a RF Transmission Status
    	    {
    		REMOVE_STRING (cTemp,'<',1)			//cTemp is now Xxxx
    		SEND_STRING 0, "'RF Trans', cTemp"
    		cReady = '0'					//ViziaRF is ready to receive a command
    		IF (cTemp == 'X002')
    		{
    		    AddtoViziaRFQue(cLastcCmd)
    		}
    	    }
    	    ACTIVE (FIND_STRING(cTemp, '<E',1)):		//Looks to see if it is an Error Message
    	    {
    		REMOVE_STRING (cTemp,'<',1)			//cTemp is now Exxx
    		SEND_STRING 0, "'Error', cTemp"
    		ON[cReady]
    	    }
    	    ACTIVE (FIND_STRING(cTemp, '<F',1)):		//Found new node message
    	    {
    		REMOVE_STRING (cTemp,'<',1)			//cTemp is now Fxxx
    		SEND_STRING 0, "'Found Node', cTemp"
    	    }
    	    ACTIVE (FIND_STRING(cTemp, '$00',1)):
    	    {
    		ON[cReady]
    	    }
    	}
        }
    }
    

    Try something like this:
    DEFINE_CONSTANT
    
    CRLF[2] = {$0D,$0A}
    
    DATA_EVENT
    
    
    STRING:
        {
         STACK_VAR CHAR cTemp[255] ; // Max 17 characters in the received data from Vizia RS232 module
         
         cTemp = "cTemp,DATA.TEXT" ;
         send_string 0, "cTemp" ;
         
         WHILE(FIND_STRING(cTemp,"CRLF",1))
    	  {
    	  STACK_VAR CHAR cParseStr[255] ;
    	  
    	  cParseStr = REMOVE_STRING(cTemp,"CRLF",1) ;
    	  SELECT
    	       {
    	       ACTIVE(FIND_STRING(cParseStr,'<N',1)):
    		    {
    		    //remove N stuff
    		    //then 
    		    //remove L stuff
    		    }
    	       ACTIVE(FIND_STRING(cParseStr,'<X',1)):
    		    {
    		    //remove X stuff
    		    }
    	       ACTIVE(FIND_STRING(cParseStr,'<E',1)):
    		    {
    		    //remove X stuff
    		    }
    	       ACTIVE(1):
    		    {
    		    //could clear cParseStr but it's a stack and will clear itself
    		    }
    
  • Joe HebertJoe Hebert Posts: 2,159
    In a previous language I have used (not a control system) I could do a split string using a delimiter and go through the array looking for what I wanted.
    You may want to check out Tech Note 662, it's a SPLIT_STRING function which can save you the time from writing your own.
  • I never saw the split_string, I looked in the Netlinx keyword help file and did not see it. Thanks.
  • I don't think this is a standard library function. You probably need to copy the function out of TN662 and paste it into your program to use SPLIT_STRING. I searched through Netlinx.axi and did not see the function.
  • Vining, I am looking at doing it by your approach and just let me know if I am correct at what I think the code does.

    It will continue looking at the data.text until it sees the CRLF, once it sees it is passes through the ACTIVE statements. So I should see them individually as <E000$0D$0A then another on as <X000$0D$0A going into the Select Actives. Instead of <E000$0D$0A<X000$0D$0A.
  • cTemp = "cTemp,DATA.TEXT" ;
         send_string 0, "cTemp" ;
         
         WHILE(FIND_STRING(cTemp,"CRLF",1))
    	  {
    

    Your're actually looking at cTemp for "$0D.$0A" not data.text.
  • I think that I am gonna use that STRING_SPLIT function from the tech note. I am wary about the ACTIVE statements not going to see all the strings that I need. So what I am thinking about doing is split it by the $0D$0A and then run it through a TO or FOR loop, that way each response is its own element.
  • Here is what I coded for the SPLIT_STRING function
    Function
    DEFINE_FUNCTION SPLIT_STRING (CHAR strINPUT[], CHAR strDELIMITER[], CHAR arOUTPUT[][])
    {
        STACK_VAR
        CHAR strTEMP[1000], strTRASH[100]
        INTEGER nLOOP, lenDELIMITER
    
        strTEMP = strINPUT //use a temporary string to keep integrity of original string
        nLOOP = 1 //variable used to track how many sub-strings there are and how many elements should be used
        lenDELIMITER = LENGTH_STRING(strDELIMITER) //length of delimiter
        WHILE(LENGTH_STRING(strTEMP)) //keep looking until the end of the string
        {
            IF(FIND_STRING(strTEMP,strDELIMITER,1)) //look for the delimiter, if it is in the string proceed
            {
                arOUTPUT[nLOOP]=REMOVE_STRING(strTEMP,strDELIMITER,1) //assign sub-strings to array element
                IF(RIGHT_STRING(arOUTPUT[nLOOP],lenDELIMITER)=strDELIMITER)
                {
                            SET_LENGTH_STRING(arOUTPUT[nLOOP],LENGTH_STRING(arOUTPUT[nLOOP])-lenDELIMITER) //remove delimiter from array element   
                }
            }
            ELSE //no more delimiters
            {
                arOUTPUT[nLOOP]=strTEMP //assign remaining portion of string to array element
                SET_LENGTH_STRING(strTEMP,0) //clear temporary string to kill loop
            }
                    SET_LENGTH_ARRAY(arOUTPUT,nLOOP) //set length of array
            nLOOP++ //increment
        }
    }
    

    DATA_EVENT [dvViziaRF]
    {
        ONLINE:
        {
    	SEND_COMMAND dvViziaRF , 'SET BAUD 9600,N,8,1'
    	AddtoViziaRFQue ('>?N')
    	AddtoViziaRFQue ('>N7,8,9GS1')			//Landscape Light Group
        }
        STRING:
        {
        	STACK_VAR CHAR cTemp[255]
    	STACK_VAR CHAR cParseTmp[255]
    	
    	cTemp = (DATA.TEXT)
    	send_string 0, "cTemp"
    	
    	SPLIT_STRING(cTemp, "CRLF", arRESULT)
    	INDEX = LENGTH_ARRAY(arRESULT)
    	FOR (INDEX=1;INDEX<=Len; INDEX++)
    	{
    	    SELECT
    	    {
    		ACTIVE(FIND_STRING(arRESULT[INDEX],'<N',1)):
    		{
    		    cParseTmp = REMOVE_STRING(arRESULT[INDEX],'<N',1)
    		    cNode = LEFT_STRING(cParseTmp,3)
    		    nNode = ATOI(cNode)
    		    cLevel = MID_STRING(cParseTmp,4,3)
    		    nLevel = ATOI(cLevel)
    		    SEND_STRING 0,"'Node', cNode"
    		    SEND_STRING 0,"'Level', cLevel"
    		    IF(nLevel = 0)
    		    {
    			nLiteStatus[nNode] = 0
    		    }
    		    ELSE
    		    {
    			nLiteStatus[nNode] = 1
    		    }
    		    SEND_STRING 0,"'Lite Status = ', nLiteStatus[nNode]"
    		}
    		ACTIVE(FIND_STRING(arRESULT[INDEX],'<X',1)):
    		{
    		    cParseTmp = REMOVE_STRING(arRESULT[INDEX],'<X',1)
    		    cRFTrans = LEFT_STRING(cParseTmp,3)	
    		    SEND_STRING 0, "'RF Trans = ',cRFTrans"
    		    IF (cRFTrans = '002')
    		    {
    			AddtoViziaRFQue(cLastcCmd)
    		    }
    		    ON[nReady]
    		}
    		ACTIVE(FIND_STRING(arRESULT[INDEX],'<G',1)):
    		{
    		    cParseTmp = REMOVE_STRING(arRESULT[INDEX], '<G',1)
    		    cGroup = LEFT_STRING(cParseTmp, 3)
    		    SEND_STRING 0, "'Group = ', cGroup"
    		    
    		}
    		ACTIVE(FIND_STRING(arRESULT[INDEX],'<F',1)):
    		{
    		    cParseTmp = REMOVE_STRING(arRESULT[INDEX],'<F',1)
    		    cFound = LEFT_STRING(cParseTmp,3)
    		    SEND_STRING 0, "'Found ',cFound"
    		}
    		ACTIVE(FIND_STRING(arRESULT[INDEX],'<E',1)):
    		{
    		    cParseTmp = REMOVE_STRING(arRESULT[INDEX],'<E',1)
    		    cError = LEFT_STRING(cParseTmp,3)
    		    SEND_STRING 0, "'Error = ',cError"
    		}
    	    }
    	}
        }
    }
    
  • I went out on-site today and had to correct the code a little bit but so far it is working pretty good. Just every now and then it lags a little sending a commands and then blasts off a bunch in a row. For instance I press Garage On and about 3-5 seconds later press Driveway On, it will take about 8-10 seconds before sending anything, and the system is not waiting for a response back to trigger nReady, it would just fire off after a while. I could not get the que to send commands correctly with this:
     If(![dvViziaRF,nReady] && Length_String(cViziaRFQue))
    

    So this is how it looks right now
    Define_Function SendViziaRFQue ()	//Send the Vizia Commands from the que
    {
        Local_Var Char cCmd[20]
        //If(![dvViziaRF,nReady] && Length_String(cViziaRFQue))
        If(!nReady && Length_String(cViziaRFQue))
        {
            cCmd = Remove_String(cViziaRFQue,"13",1)
    	cLastcCmd = cCmd
            SEND_STRING dvViziaRF,"cCmd"
            Send_String 0,"'Sent Leviton Command: ',cCmd"
    	ON[nReady]
        }
    }
    
  • The nReady should be renamed to nBusy. Then the statement !nReady would make more sense. It would now read if !nBusy. So if NOT BUSY (!nbusy) and there is length in the command buffer then parse it. When and where do you turn off the nReady (nBusy)?
  • I turn off the nReady(nBusy) in the Data Event when I receive X000 or X002 which means the device is ready for the next command
  • So if you don't get either of those strings the command buffer does not parse. Correct? I would clear the busy state on any string coming back and drop the busy state after .5 seconds. The device should provide a response well before then.
  • I was watching it as it happened and the nReady was always getting cleared, but I can clear it after so long I think I would be more comfortable with 1 second the device is a little sluggish on the responses. I think I am actually seeing a connectivity problem more than an issue with the code. I was there today and I was having some issues on the wireless with my laptop.
Sign In or Register to comment.