Home AMX User Forum NetLinx Studio

Parsing incoming string of varying length help

Being a bit of a novice I have a question about incoming strings and extracting the information. I've used LEFT_STRING, RIGHT_STRING, MID_STRING before for various things, but I'm not sure how to go about retrieving the information for the following:

I have a large video matrix (512 in x 128 out) that has custom software inside that sends a serial string anytime a change has been made. I then take that string and extract the change and send a different string to an audio matrix. The string does have a start and end bit, but can have multiple changes. I need to be able to extract each change and send a string to the audio matrix. An example of a single change in the video matrix is as follows: 0x02M0001C00002L000000100x03 (the 0x02 is the start and the 0x03 is the end. In this case in need to extract M0001 and C00002 and can ignore the rest. I need to assign the M and C numbers to different variables. The matrix can also send multiple changes within the 0x02 - 0x03. It just repeats the M____C____L____ format within the start and stop bits. So it could look like: 0x02M0001C00003L00000100M0003C00010L000003000x03

I take the M number and the C number and translate that into a string that the audio matrix can use and send it. Any suggestions on extracting the information I need?

Thanks

Comments

  • If M, C and L always have the same length you can use GET_BUFFER_STRING.
    GET_BUFFER_CHAR(DATA.TEXT)  // Pulls out the $02
    sMyMVariable = GET_BUFFER_STRING(DATA.TEXT,5)  // Pulls out M0001
    sMyCVariable = GET_BUFFER_STRING(DATA.TEXT,6)  // Pulls out C00003
    sMyLVariable = GET_BUFFER_STRING(DATA.TEXT,9)  // Pulls out L00000100
    
    
  • zooeylzooeyl Posts: 13
    Thanks, M, C, & L are always the same length. I'll give that a try. Much appreciated.
  • AMXJeffAMXJeff Posts: 450
    zooeyl wrote:
    Thanks, M, C, & L are always the same length. I'll give that a try. Much appreciated.

    This is another method, it will get all the M C L values and in the string... This method does not care how long the each M C L are. If the values of M C L exceed an integer, make all the integers LONGs.
    (***********************************************************)
    (*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_DEVICE
    dvRS232 = 5001:1:0
    
    (***********************************************************)
    (*               VARIABLE DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_VARIABLE
    VOLATILE CHAR cBuffer[1000];
    
    (***********************************************************)
    (*        SUBROUTINE/FUNCTION DEFINITIONS GO BELOW         *)
    (***********************************************************)
    DEFINE_FUNCTION DO_SOMETHING(INTEGER nM, INTEGER nC, INTEGER nL)
    {
    	// do something with the informationm
    }
    
    DEFINE_FUNCTION ParseBuffer(CHAR cMsg[])
    {
    	STACK_VAR INTEGER M_VALUE;
    	STACK_VAR INTEGER C_VALUE;
    	STACK_VAR INTEGER L_VALUE;
    	
    	WHILE (FIND_STRING(cMsg,'M',1) && FIND_STRING(cMsg,'C',1) && FIND_STRING(cMsg,'L',1))
    	{
    		REMOVE_STRING(cMsg,'M',1);
    		
    		M_VALUE = ATOI(cMsg);
    
    		REMOVE_STRING(cMsg,'C',1);
    		
    		C_VALUE = ATOI(cMsg);
    
    		REMOVE_STRING(cMsg,'L',1);
    		
    		L_VALUE = ATOI(cMsg);
    		
    		DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE);
    	}
    }
    
    (***********************************************************)
    (*                STARTUP CODE GOES BELOW                  *)
    (***********************************************************)
    DEFINE_START
    
    CREATE_BUFFER dvRS232, cBuffer
    (***********************************************************)
    (*                THE EVENTS GO BELOW                      *)
    (***********************************************************)
    DEFINE_EVENT
    
    DATA_EVENT[dvRS232]
    {
    	STRING:
    	{
    		WHILE(FIND_STRING(cBuffer,"$03",1));
    			ParseBuffer(REMOVE_STRING(cBuffer,"$03",1));
    	}
    }
    
    (***********************************************************)
    (*                     END OF PROGRAM                      *)
    (*        DO NOT PUT ANY CODE BELOW THIS COMMENT           *)
    (***********************************************************)
    
    
  • JeffJeff Posts: 374
    are you sure Jeff? I think you're missing a little bit of code in your ParseBuffer function.

    something like . . .
    DEFINE_FUNCTION ParseBuffer(CHAR cMsg[])
    {
    	STACK_VAR INTEGER M_VALUE;
    	STACK_VAR INTEGER C_VALUE;
    	STACK_VAR INTEGER L_VALUE;
    	
    	WHILE (FIND_STRING(cMsg,'M',1))
    	{
    		REMOVE_STRING(cMsg,'M',1);
    		M_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'C',1)-1))
    		REMOVE_STRING(cMsg,'C',1);
    		C_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'L',1)-1))
    		REMOVE_STRING(cMsg,'L',1);
    		L_VALUE = ATOI(cMsg);
    		DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE);
    	}
    }
    
  • AMXJeffAMXJeff Posts: 450
    Jeff wrote:
    are you sure Jeff? I think you're missing a little bit of code in your ParseBuffer function.

    something like . . .
    DEFINE_FUNCTION ParseBuffer(CHAR cMsg[])
    {
    	STACK_VAR INTEGER M_VALUE;
    	STACK_VAR INTEGER C_VALUE;
    	STACK_VAR INTEGER L_VALUE;
    	
    	WHILE (FIND_STRING(cMsg,'M',1))
    	{
    		REMOVE_STRING(cMsg,'M',1);
    		M_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'C',1)-1))
    		REMOVE_STRING(cMsg,'C',1);
    		C_VALUE = ATOI(left_string(cMsg,find_string(cMsg,'L',1)-1))
    		REMOVE_STRING(cMsg,'L',1);
    		L_VALUE = ATOI(cMsg);
    		DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE);
    	}
    }
    

    Positive, ATOI will parse until it gets to the first non-numeric ascii char. No need to do the left strings... Try it, it works really cool!!!!!
  • +1. The fact that ATOI behaves as it does (not evaluating anything beyond the first valid numeric characters it finds) saves a ton of extra coding, and allows for numbers coming in to be of any character length without screwing things up.

    - Chip

    AMXJeff wrote:
    Positive, ATOI will parse until it gets to the first non-numeric ascii char. No need to do the left strings... Try it, it works really cool!!!!!
  • JeffJeff Posts: 374
    Nifty . . . . learn something new every day.

    OTOH, if he doesn't want an integer value, and he actually wants the characters, he'd need to do the left strings.

    I'm gonna have to remember ATOI works that way though, thats a new one on me.

    J
  • AMXJeffAMXJeff Posts: 450
    Actually in your case, you can do a ITOA(ATOI(cMsg)) and get the ascii chars back with out the leading zeros... Just another neat trick....
    Jeff wrote:
    Nifty . . . . learn something new every day.

    OTOH, if he doesn't want an integer value, and he actually wants the characters, he'd need to do the left strings.

    I'm gonna have to remember ATOI works that way though, thats a new one on me.

    J
  • zooeylzooeyl Posts: 13
    Thanks everybody. All I need are the numeric values, so the ATOI will work just fine.
  • LEFT_STRING is great when you're guaranteed to have a fixed-length string, (In the case of the OP, he'd be in luck) but you can use REMOVE_STRING on both fixed and variable length string responses and get what you need. In the case of "M____C____L____" - for example - you could do
    REMOVE_STRING(cMsg,'M',1)
    M_VALUE = REMOVE_STRING(cMsg,'C',1)  // "M_VALUE" is a character var here
    SET_LENGTH_STRING (M_VALUE,(LENGTH_STRING(M_VALUE)-1))  // Nuke the 'C' off the end
    

    This will get you the characters you like regardless of how many there are between the 'M' and the 'C'.

    If you don't care about leading zeros, AMXJeff's solution rocks - works great for getting verbose device feedback values up onto an indirect text button in a more human-friendly way.

    - Chip

    Jeff wrote:
    Nifty . . . . learn something new every day.

    OTOH, if he doesn't want an integer value, and he actually wants the characters, he'd need to do the left strings.

    J
  • zooeylzooeyl Posts: 13
    Thanks again for the help. Here's another scenario to make things one step more complicated. It is theoretically possible for the Video Matrix to send out multiple changes between the $02 and $03. For example:

    $02M0001C00002L00000010M0002C00005L00000222$03

    With multiple instances of M, C, & L how would you extract each instance individually?
  • AMXJeffAMXJeff Posts: 450
    My code above handles multiple instances of M C L... The function dosomething will be triggered after each set of M C L have been parsed. So in your case below dosomething will be triggered twice. Hope this helps... See the same code below for ease of reading...
    (***********************************************************)
    (*          DEVICE NUMBER DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_DEVICE
    dvRS232 = 5001:1:0
    
    (***********************************************************)
    (*               VARIABLE DEFINITIONS GO BELOW             *)
    (***********************************************************)
    DEFINE_VARIABLE
    VOLATILE CHAR cBuffer[1000];
    
    (***********************************************************)
    (*        SUBROUTINE/FUNCTION DEFINITIONS GO BELOW         *)
    (***********************************************************)
    DEFINE_FUNCTION DO_SOMETHING(INTEGER nM, INTEGER nC, INTEGER nL)
    {
    	// do something with the informationm
    }
    
    DEFINE_FUNCTION ParseBuffer(CHAR cMsg[])
    {
    	STACK_VAR INTEGER M_VALUE;
    	STACK_VAR INTEGER C_VALUE;
    	STACK_VAR INTEGER L_VALUE;
    	
    	WHILE (FIND_STRING(cMsg,'M',1) && FIND_STRING(cMsg,'C',1) && FIND_STRING(cMsg,'L',1))
    	{
    		REMOVE_STRING(cMsg,'M',1);
    		
    		M_VALUE = ATOI(cMsg);
    
    		REMOVE_STRING(cMsg,'C',1);
    		
    		C_VALUE = ATOI(cMsg);
    
    		REMOVE_STRING(cMsg,'L',1);
    		
    		L_VALUE = ATOI(cMsg);
    		
    		DO_SOMETHING(M_VALUE, C_VALUE, L_VALUE);
    	}
    }
    
    (***********************************************************)
    (*                STARTUP CODE GOES BELOW                  *)
    (***********************************************************)
    DEFINE_START
    
    CREATE_BUFFER dvRS232, cBuffer
    (***********************************************************)
    (*                THE EVENTS GO BELOW                      *)
    (***********************************************************)
    DEFINE_EVENT
    
    DATA_EVENT[dvRS232]
    {
    	STRING:
    	{
    		WHILE(FIND_STRING(cBuffer,"$03",1));
    			ParseBuffer(REMOVE_STRING(cBuffer,"$03",1));
    	}
    }
    
    (***********************************************************)
    (*                     END OF PROGRAM                      *)
    (*        DO NOT PUT ANY CODE BELOW THIS COMMENT           *)
    (***********************************************************)
    

    zooeyl wrote:
    Thanks again for the help. Here's another scenario to make things one step more complicated. It is theoretically possible for the Video Matrix to send out multiple changes between the $02 and $03. For example:

    $02M0001C00002L00000010M0002C00005L00000222$03

    With multiple instances of M, C, & L how would you extract each instance individually?
Sign In or Register to comment.