Home AMX User Forum NetLinx Studio

Create_Buffer question

Hey,

So I'm interfacing with a Lifesize Room 220 via RS-232. It likes sending lots and lots of strings to me when calls are happening, and all the strings I'm thinking go into a buffer. But how do most people prefer to handle large volumes of strings? I'm thinking:
Data_Event
{
 String:
  {
   //do stuff with the buffer in here
  }
}
But then what if two strings come in close to each other? The next string will get tacked onto the end of the buffer but I'll never know about it?

Or else you could:
Define_Program
{
 IF (length_array(sbuffer)>0)
 {
  //do stuff with the buffer in here
 }
}

Just curious. Am I being a worrywort about missing some strings? Are the chances that two come in on top of one another really big enough to care about?

Comments

  • truetrue Posts: 307
    Is there any way with the protocol of knowing the length or end of a command? If not, the protocol sucks. :(
  • jcereckejcerecke Posts: 40
    It delimits with a comma
    It starts a new line with "$0D,$0A"
    It ends a string with "'ok,00',$0D,$0A"
  • mushmush Posts: 287
    jcerecke wrote: »
    Data_Event
    {
     String:
      {
       //do stuff with the buffer in here
      }
    }
    



    Definitely this method.
    Each time a string comes in it will be appended to DATA.TEXT which you can then troll through and rip out what you need and throw away the rest.

    Cheers

    Mush
  • PhreaKPhreaK Posts: 966
    If you're sure that rx commands are not split across multiple events this should be what you're chasing:
    data_event[device] {
        string: {
            stack_var char rx[32]    // <--- make this bigger if you need to
            while (find_string(data.text, "'ok,00',$0D,$0A", 1) {
                rx = remove_string(data.text, "'ok,00',$0D,$0A", 1)
                parseResponse(rx)    //do stuff with the rx data here
            }
        }
    }
    

    Or alternatively, if you're wanting all lines and not just what I presume are ACK's:
    data_event[device] {
        string: {
            stack_var char rx[32]    // <--- make this bigger if you need to
            while (find_string(data.text, "'$0D,$0A", 1) {
                rx = remove_string(data.text, "'$0D,$0A", 1)
                parseResponse(rx)    //do stuff with the rx data here
            }
        }
    }
    

    jcerecke wrote: »
    Am I being a worrywort about missing some strings? Are the chances that two come in on top of one another really big enough to care about?
    Definately not. Things can get dodgy real quickly if you start missing data. For the control system it's the equivalent of walking into a conversation half way through - as soon as it starts talking it'll make an *** of itself.
  • DHawthorneDHawthorne Posts: 4,584
    You can most assuredly get more than one actual event from a STRING handler, and you can just as easily get only part of one ... when you are talking to a real device. It's perfectly safe to assume DATA.TEXT contains your full and proper string when it is a virtual device getting data from an internal process, but all bets are off talking to an IP or serial device. It works on a timer basis; when it sees a pause in the data flow, it assumes the string is done and generates the event (presumably ignoring flow control pauses, but I don't really know that for sure). If the pause is too brief, or circumstances cause one for reasons other than the string is actually done, you will not have what you expect in there. That's when you use a buffer ... whether you create or manage your own or use the build in methods.
  • the8thstthe8thst Posts: 470
    You can get around the problem of a string getting split between data events easily by adding a buffer to the example. You will also want to add some error checking to clear out the buffer if it gets filled with junk or a string from the device get messed up.
    PhreaK wrote: »
    If you're sure that rx commands are not split across multiple events this should be what you're chasing:
    define_variable
    volatile char devBuffer[255] // <-- adjust size to what is appropriate
    
    data_event[device] {
        string: {
            stack_var char rx[32]    // <--- make this bigger if you need to
           
            devBuffer = "devBuffer,data.text"
            while (find_string(devBuffer, "'ok,00',$0D,$0A", 1) {
                rx = remove_string(devBuffer, "'ok,00',$0D,$0A", 1)
                parseResponse(rx)    //do stuff with the rx data here <-- It is best to use a function here
            }
        }
    }
    

    Or alternatively, if you're wanting all lines and not just what I presume are ACK's:
    define_variable
    volatile char devBuffer[255] // <-- Adjust size to apropriate
    
    data_event[device] {
        string: {
            stack_var char rx[32]    // <--- make this bigger if you need to
    
            devBuffer = "devBuffer,data.text"
            while (find_string(devBuffer, "'$0D,$0A", 1) {
                rx = remove_string(devBuffer, "'$0D,$0A", 1)
                parseResponse(rx)    //do stuff with the rx data here
            }
        }
    }
    



    Definately not. Things can get dodgy real quickly if you start missing data. For the control system it's the equivalent of walking into a conversation half way through - as soon as it starts talking it'll make an *** of itself.
  • Spire_JeffSpire_Jeff Posts: 1,917
    You can also use the CREATE_BUFFER command. This will dump all incoming text into the buffer variable, then just use while statement in the data_event string section.

    Jeff
  • the8thstthe8thst Posts: 470
    Spire_Jeff wrote: »
    You can also use the CREATE_BUFFER command. This will dump all incoming text into the buffer variable, then just use while statement in the data_event string section.

    Jeff


    That works as well.
  • jcereckejcerecke Posts: 40
    Spire_Jeff wrote: »
    You can also use the CREATE_BUFFER command. This will dump all incoming text into the buffer variable, then just use while statement in the data_event string section.

    You mean this type of arrangement?:
    while buffer is longer than ''
    {
    parse buffer up until the next ACK
    }

    Next question is this:
    Lets say a string comes in, string event fires and during the while loop, a second string comes in. Will a second string event fire?
    The while loop from the first string event will parse the second string (and remove it from buffer) and the second string event will try and start a while loop which will immediately break? Not that this will cause any problems.

    Thanks for the help thus far!
  • PhreaKPhreaK Posts: 966
    If you're using a standard while you will only be working with the data that triggered that event. Anything else that comes in while you're crunching away on the first event is queued up. If you use a long_while things will start to get wierd as the message queues are processed after each loop iteration.
  • viningvining Posts: 4,368
    jcerecke wrote: »
    You mean this type of arrangement?:
    while buffer is longer than ''
    {
    parse buffer up until the next ACK
    }

    Next question is this:
    Lets say a string comes in, string event fires and during the while loop, a second string comes in. Will a second string event fire?
    The while loop from the first string event will parse the second string (and remove it from buffer) and the second string event will try and start a while loop which will immediately break? Not that this will cause any problems.

    Thanks for the help thus far!

    Here's a couple of exmples:
    STRING:
    	  {
    	  STACK_VAR INTEGER nFBS ;
    	  
    	  //fnDevMod_DeBug("'RX_STR: "',DATA.TEXT,'" :DEBUG <',ITOA(__LINE__),'>'") ;
    	  
    	  sNuVTV.cRX_Buff = "sNuVTV.cRX_Buff,DATA.TEXT" ;
    	 
    	 	  
    	  WHILE(find_string(sNuVTV.cRX_Buff,"STR_ETX",1))
    	       {
    	       nFBS = find_string(sNuVTV.cRX_Buff,"STR_ETX",1) ;
    	       if(nFBS > 1)
    		    {
    		    fnDevMod_String(GET_BUFFER_STRING(sNuVTV.cRX_Buff,nFBS-1)) ;
    		    GET_BUFFER_CHAR(sNuVTV.cRX_Buff) ;
    		    }
    	       else
    		    {
    		    GET_BUFFER_CHAR(sNuVTV.cRX_Buff) ;
    		    }
    	       }
    
    STRING:
         {
         STACK_VAR CHAR cTV_TempBuf[25] ;
         LOCAL_VAR CHAR cRX_Data[256] ;
         
         CANCEL_WAIT 'CLEAR_RX_DATA' ;
         cRX_Data = "cRX_Data,DATA.TEXT" ;
         WHILE(FIND_STRING(cRX_Data,"PSEND_ETX",1)) // while there's an end of message bit in the buffer
    	  {
    	  STACK_VAR INTEGER nFBS ;
    	  
    	  //fnDeBug_TV("'RX from DPS: ',fnDEV_TO_STRING(DATA.DEVICE),', ',DATA.TEXT,' >-Line-<',ITOA(__LINE__),'>'") ;
    	  
    	  REMOVE_STRING(cRX_Data,"PSEND_STX",1) ;
    	  nFBS = FIND_STRING(cRX_Data,"PSEND_ETX",1) ;
    	  if(nFBS)
    	       {
    	       cTV_TempBuf = GET_BUFFER_STRING(cRX_Data,nFBS - 1) ; 
    	       REMOVE_STRING(cRX_Data,"PSEND_ETX",1) ; ; //remove ETX
    	       //cTV_ReturnedStr = cTV_TempBuf ; //remove after testing complete
    	       fnDeBug_TV("'RX from DPS: ',fnDEV_TO_STRING(DATA.DEVICE),', ',cTV_TempBuf,' >-Line-<',ITOA(__LINE__),'>'") ;
    	       fnTV_ParseBuf(cTV_TempBuf) ;
    	       }
    	  else
    	       {
    	       //no ETX?? must have been in front of STX!!!
    	       }
    	  }
         WAIT 40 'CLEAR_RX_DATA'
    	  {
    	  CLEAR_BUFFER cRX_Data ;
    	  }
    
  • DHawthorneDHawthorne Posts: 4,584
    PhreaK wrote: »
    If you're using a standard while you will only be working with the data that triggered that event. Anything else that comes in while you're crunching away on the first event is queued up. If you use a long_while things will start to get wierd as the message queues are processed after each loop iteration.

    I may be misremembering, but I think that only applies to Axcess. In NetLinx there is no distinction between WHILEs and LONG_WHILEs. NetLinx is also only single-threaded. When a WHILE is executing, nothing else is happening or being processed. As result, I tend to make sure I only use them when I know it's going to be a very short time period. I had to port an involved math function that used a while to iterate through some very small increments, and it pretty much locked up the master while it was running. I had to sacrifice most of the resolution of the function to make it usable at all, and even then there was a noticeable hiccup in the processor when it ran.
Sign In or Register to comment.